Skip to content

Instantly share code, notes, and snippets.

@rxgx
Last active April 18, 2018 23:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rxgx/2430400476ae32bc44b7b9052feaeab1 to your computer and use it in GitHub Desktop.
Save rxgx/2430400476ae32bc44b7b9052feaeab1 to your computer and use it in GitHub Desktop.
Auth0 rule to save an encrypted version of Google's refresh token to a user's app_metadata
function (user, context, callback) {
const namespace = 'https://grateful.digital/';
if (
user.app_metadata &&
user.app_metadata.refresh_token_encrypted
) {
const refreshTokenEncrypted = user.app_metadata.refresh_token_encrypted;
context.idToken[namespace + 'refresh_token_encrypted'] = refreshTokenEncrypted;
}
callback(null, user, context);
}
/**
* Store Google Refresh Token
*
* In some scenarios, you might want to access Google APIs from your application. You
* do that by using the access_token stored on the identities array
* (user.identities[0].access_token). However access_tokens have an expiration and in
* order to get a new one, you have to ask the user to login again. That's why Google
* allows asking for a refresh_token that can be used forever (until the user revokes
* it) to obtain new access_tokens without requiring the user to relogin.
*
* The way you ask for a refresh_token using Lock is by sending the access_type=offline
* as an extra parameter as explained here using the auth.params object in Lock's options.
*
* The only caveat is that Google will send you the refresh_token only once, and if you
* haven't stored it, you will have to ask for it again and add approval_prompt=force
* so the user explicitly consent again. Since this would be annoying from a user
* experience perspective, you should store the refresh token on Auth0 as a persistent
* property of the user, only if it there is a new one available.
*
* https://auth0.com/rules/google-refresh-token
*/
function (user, context, callback) {
user.app_metadata = user.app_metadata || {};
// IMPORTANT: for greater security, we recommend encrypting this value and decrypt on your application.
function encryptAesSha256(password, textToEncrypt) {
var cipher = crypto.createCipher('aes-256-cbc', password);
var crypted = cipher.update(textToEncrypt, 'utf8', 'hex');
crypted += cipher.final('hex');
return crypted;
}
// get the google identity
var googleIdentity = _.find(user.identities, { provider: 'google-oauth2' });
// if the user that just logged in has a refresh_token, persist it
if (googleIdentity && googleIdentity.refresh_token) {
var refresh_token_encrypted = encryptAesSha256(
configuration.cipherKey,
googleIdentity.refresh_token
);
user.app_metadata.refresh_token_encrypted = refresh_token_encrypted;
auth0.users
.updateAppMetadata(user.user_id, user.app_metadata)
.then(function() {
callback(null, user, context);
})
.catch(function(err) {
callback(err);
});
} else {
callback(null, user, context);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment