- Passwordless Login
- Organizations
- WebAuth.client.login(options, callback)
- Get and use a Refresh token
- Custom Token Exchange
For information on how to implement Passwordless Login with this SDK, please read Passwordless Login on Auth0 Docs.
Organizations is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications.
To log in to a specific organization, pass the ID, or name, of the organization as the organization parameter when creating the WebAuth client:
var webAuth = new WebAuth({
domain: '{YOUR_AUTH0_DOMAIN}',
clientID: '{YOUR_AUTH0_CLIENT_ID}',
organization: '{YOUR_AUTH0_ORGANIZATION_ID_OR_NAME}'
});You can also specify an organization when calling authorize:
webAuth.authorize({
organization: '{YOUR_AUTH0_ORGANIZATION_ID_OR_NAME}'
});Accept a user invitation through the SDK by creating a route within your application that can handle the user invitation URL, and log the user in by passing the organization and invitation parameters from this URL. You can either use authorize or popup.authorize as needed.
var url = new URL(invitationUrl)
var params = new URLSearchParams(url.search);
if (organization && invitation) {
webAuth.authorize({
organization: params.get('organization')
invitation: params.get('invitation')
});
}When working with organizations, you might want to store the organization to ensure subsequent renewals of tokens using checkSession do not lose the context of the last used organization.
auth0.parseHash({}, ({ idTokenPayload }) => {
var organization = idTokenPayload.org_id || idTokenPayload.org_name;
// store organization somewhere that persists across page-refreshes
// - localstorage
// - cookie
localStorage.setItem('app_organization', organization);
});With the organization stored in a persistent storage, you want to ensure it's always pulled in from there when calling checkSession:
webAuth.checkSession(
{
organization: localStorage.setItem('app_organization')
},
() => {}
);Additionally, you also want to ensure to read the last used organization when instantiating WebAuth on every subsequent page refresh.
var webAuth = new WebAuth({
domain: '{YOUR_AUTH0_DOMAIN}',
clientID: '{YOUR_AUTH0_CLIENT_ID}',
organization: localStorage.setItem('app_organization')
});Authenticates a user with username and password in a realm using /oauth/token. This will not initialize a SSO session at Auth0, hence can not be used along with silent authentication.
var auth0 = new auth0.WebAuth({
domain: '{YOUR_AUTH0_DOMAIN}',
clientID: '{YOUR_AUTH0_CLIENT_ID}'
});
auth0.client.login(
{
realm: 'Username-Password-Authentication', //connection name or HRD domain
username: 'info@auth0.com',
password: 'areallystrongpassword',
audience: 'https://mystore.com/api/v2',
scope: 'read:order write:order'
},
function (err, authResult) {
// Auth tokens in the result or an error
}
);The contents of authResult are identical to those returned by parseHash().
onRedirecting hook
When using login to log in using a username and password, Auth0.js initially makes a call to Auth0 to get a login ticket, before sending that login ticket to the /authorize endpoint to be exchanged for tokens. You are able to specify an onRedirecting hook here to handle when Auth0.js is about to redirect to the /authorize endpoint, for the purposes of executing some custom code (analytics, etc).
To do this, specify the onRedirecting function in the options and ensure that the done callback is called when you are finished executing your custom code. Otherwise, authentication will be blocked.
auth0.client.login(
{
realm: 'Username-Password-Authentication', //connection name or HRD domain
username: 'info@auth0.com',
password: 'areallystrongpassword',
onRedirecting: function (done) {
// Your custom code here
done();
}
},
function (err, authResult) {
// Auth tokens in the result or an error
}
);How to obtain and generate a refresh_token to use it for getting new access_tokens.
To do this, set responseType to code when creating the WebAuth client:
var webAuth = new auth0.WebAuth({
domain: '{YOUR_AUTH0_DOMAIN}',
redirectUri: '{YOUR_REDIRECT_URI}',
clientID: '{YOUR_CLIENT_ID}',
responseType: 'code',
});Call authorize, add offline_access as part of the scope:
webAuth.authorize({
audience: '{THE_AUDIENCE}',
scope: 'offline_access'
});code can be obtained as a string param in the callback
Exchange the obtained code to get an access_token and the refresh_token:
webAuth.client.oauthToken(
{
code,
grantType: 'authorization_code',
redirectUri: '{YOUR_REDIRECT_URI}',
}, function(err, result) {
if (!err) {
// result.refreshToken
}
}
);Use the refresh_token to generate access_token
webAuth.client.oauthToken(
{
grantType: 'refresh_token',
clientID: '{YOUR_CLIENT_ID}',
refresh_token: '{THE_REFRESH_TOKEN}',
}
);Additionally, if your tenant supports Multi-Resource Refresh Token (MRRT), you can use a refresh_token to get an access_token with a different audience and/or scope.
webAuth.client.oauthToken(
{
grantType: 'refresh_token',
clientID: '{YOUR_CLIENT_ID}',
refresh_token: '{THE_REFRESH_TOKEN}',
audience: '{OTHER_AUDIENCE}',
scope: '{OTHER_SCOPE}'
}
);Custom Token Exchange allows you to exchange an external subject token (from a third-party identity provider, legacy system, or custom authentication mechanism) for Auth0 tokens using RFC 8693.
For more information, please read Custom Token Exchange on Auth0 Docs.
var auth0 = new auth0.WebAuth({
domain: '{YOUR_AUTH0_DOMAIN}',
clientID: '{YOUR_AUTH0_CLIENT_ID}'
});
auth0.client.customTokenExchange(
{
subjectToken: 'eyJhbGciOiJSUzI1NiIs...',
subjectTokenType: 'urn:acme:legacy-system-token'
},
function (err, result) {
if (err) {
console.error('Token exchange failed:', err.code, err.description);
return;
}
console.log('Access token:', result.accessToken);
console.log('ID token:', result.idToken);
}
);You can also call customTokenExchange directly on the WebAuth instance:
auth0.customTokenExchange(
{
subjectToken: 'eyJhbGciOiJSUzI1NiIs...',
subjectTokenType: 'urn:acme:legacy-system-token'
},
function (err, result) {
// Auth tokens in the result or an error
}
);Override the default audience and scope configured on the client:
auth0.client.customTokenExchange(
{
subjectToken: 'eyJhbGciOiJSUzI1NiIs...',
subjectTokenType: 'urn:acme:legacy-system-token',
audience: 'https://mystore.com/api/v2',
scope: 'openid profile read:orders'
},
function (err, result) {
// result.accessToken is scoped to the specified audience
}
);If audience or scope are not provided, they fall back to the values configured when creating the WebAuth or Authentication client.
auth0.client.customTokenExchange(
{
subjectToken: 'eyJhbGciOiJSUzI1NiIs...',
subjectTokenType: 'urn:acme:sso-token',
organization: 'org_12345'
},
function (err, result) {
// Tokens are scoped to the specified organization
}
);Arbitrary parameters can be included and are forwarded to the /oauth/token endpoint. These are accessible in Auth0 Actions via event.request.body.
auth0.client.customTokenExchange(
{
subjectToken: 'firebase-id-token',
subjectTokenType: 'urn:acme:firebase-token',
migrationSource: 'firebase',
userRegion: 'eu-west-1'
},
function (err, result) {
// Auth0 Action can read event.request.body.migration_source
// and event.request.body.user_region
}
);Note: Parameter keys are converted from camelCase to snake_case before being sent. For example,
migrationSourcebecomesmigration_sourcein the request body.
Client-side validation errors (missing required parameters) are thrown synchronously:
try {
auth0.client.customTokenExchange(
{ subjectTokenType: 'urn:acme:token' }, // subjectToken is missing
function () {}
);
} catch (e) {
console.error(e.message); // "subjectToken option is required"
}Server-side errors are returned via the callback:
auth0.client.customTokenExchange(
{
subjectToken: 'invalid-token',
subjectTokenType: 'urn:acme:token'
},
function (err, result) {
if (err) {
// err.code — e.g., 'invalid_grant', 'unauthorized_client', 'access_denied'
// err.description — human-readable error description
// err.statusCode — HTTP status code
console.error(err.code + ': ' + err.description);
return;
}
}
);