Search code examples
authenticationauth0

Using Auth0 to authenticate against multiple resources with a single application login


My app is authenticated using Auth0. The user enters their username + password and Auth0 gives back a token which my app uses to call my backend.

My app also uses 3rd party applications behind the scenes, and those 3rd party applications all have their own authentication. When a user logs in to my application, it needs to go out and get authentication tokens for all these 3rd party apps as well.

For example, my app needs to use an API on Watson which is authenticated using a different username + password. The user can’t know what that username + password are. Instead, they are ‘known’ by my app, which uses them to login to Watson and get an auth token to make the API calls.

That Watson API isn’t the only 3rd party API my app needs to use. The 3rd party APIs all have their own authentication schemes. Some use a username + password, others use an App ID and Secret, etc. But in all of these cases, the authentication credentials are owned and managed by my application - not by the user of my application.

So the question is, how can I use Auth0 to automatically go out and get all these 3rd party authentication tokens when the user logs in to my app?


Solution

  • When the user has authenticated with Auth0, the client will receive JSON Web Token (JWT) that can be used with APIs server or other 3rd party servers. It also contains the information about the user such as UID or email.

    See https://auth0.com/learn/json-web-tokens/

    In order to use Auth0 to automatically get all 3rd party authentication tokens, you can simply use Rules to get those tokens and merge it with your idToken. The client can then decode the JWT and get the token or secret it needed.

    Rules are JavaScript code that will execute after the user is authenticated.

    Here is the sample code from Auth0

    function (user, context, callback) {
    
    // this is the private key you downloaded from your service account.
    // make sure you remove the password from the key and convert it to PEM using the following
    // openssl pkcs12 -in yourkey.p12 -out yourkey.pem -nocerts -nodes
    // finally, you should put this as a configuration encrypted in Auth0
    var KEY = '....RSA private key downloaded from service account...'; 
    
    // this is the email address of the service account created (NOT the Client ID)
    var GOOGLE_CLIENT_ID_EMAIL = '[email protected]';
    
    // the scope you want access to. Full list of scopes https://developers.google.com/admin-sdk/directory/v1/guides/authorizing
    var SCOPE = 'https://www.googleapis.com/auth/admin.directory.user.readonly';
    
    // a user of your Google Apps domain that this rule would impersonate
    var ADMIN_EMAIL = '[email protected]';
    
    var token = jwt.sign({ scope: SCOPE, sub: ADMIN_EMAIL }, KEY, { audience: "https://accounts.google.com/o/oauth2/token", issuer: GOOGLE_CLIENT_ID_EMAIL, expiresInMinutes: 60, algorithm: 'RS256'});
    
    request.post({ url: 'https://accounts.google.com/o/oauth2/token', form: { grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: token } }, function(err, resp, body) {
        if (err) return callback(null, user, context);
        var result = JSON.parse(body);
        if (result.error) {
        console.log(body);
        // log and swallow
        return callback(null, user, context);
        }
    
        context.idToken['https://example.com/admin_access_token'] = result.access_token;
        callback(null, user, context);
    });
    
    }
    

    After user logged in, this rule will request the Access_token from Google then put it in the response idToken. You can use this similar pattern for other APIs.

    See https://auth0.com/docs/rules