Last active
April 18, 2018 23:03
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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