-
-
Notifications
You must be signed in to change notification settings - Fork 141
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Social auth] Easy refresh token management #917
Labels
Comments
@LoicPoullain Hi! I remember that i've made two methods for encrypt and decrypt a string using a secret from config in AbstractProvider. This could be used for solving issue 1. 👍 /**
* This function is for encrypt a string using aes-256 and codeVerifierSecret.
* Notice that init vector base64-encoded is concatenated at start of encrypted message.
* We'll need init vector to decrypt message.
* Init vector is 16 bytes length and it base64-encoded is 24 bytes length.
*
* @param {string} message - String to encrypt
*/
private encryptString(message: string): string {
const hashedSecret = this.getCodeVerifierSecretBuffer();
// Initiate iv with random bytes
const initVector = crypto.randomBytes(16);
// Create cipher
const cipher = crypto.createCipheriv(this.cryptAlgorithm, hashedSecret, initVector);
// Encrypt data, concat final
const data = cipher.update(Buffer.from(message));
const encryptedMessage = Buffer.concat([data, cipher.final()])
return `${initVector.toString('base64')}${encryptedMessage.toString('base64')}`
}
/**
* This function is for decrypt a string using aes-256 and codeVerifierSecret
* encryptedMessage is {iv}{encrypted data}
*
* @param {string} encryptedMessage - String to decrypt
*/
private decryptString(encryptedMessage: string): string {
const hashedSecret = this.getCodeVerifierSecretBuffer();
// Get init vector back from encryptedMessage
const initVector: Buffer = Buffer.from(encryptedMessage.substring(0,24), 'base64'); // original iv is 16 bytes long, so base64 encoded is 24 bytes long
const message: string = encryptedMessage.substring(24);
// Create decipher
const decipher = crypto.createDecipheriv(this.cryptAlgorithm, hashedSecret, initVector);
// Decrypt data, concat final
const data = decipher.update(Buffer.from(message, 'base64'));
const decryptedMessage = Buffer.concat([data, decipher.final()])
return decryptedMessage.toString()
}
private getCodeVerifierSecretBuffer(): Buffer {
// Get secret from config file or throw an error if not defined
const codeVerifierSecret = Config.getOrThrow(this.codeVerifierSecretPath, 'string');
// We create a sha256 hash to ensure that key is 32 bytes long
return crypto.createHash('sha256').update(codeVerifierSecret).digest();
}
`
`` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Issue
Currently, Foal allows users to be authenticated through social providers. Through social services, the application can authenticate users with Google, for example, and in return get user information as well as access and refresh tokens to communicate with the Google API.
Issue 1
However, there is no "easy" way to store securely the refresh token for later communication with the API. We can store the refresh token in the session using
ctx.session.set('refreshToken', tokens.refresh_token)
but then the token is saved in plain text in the database. This can cause security problems if the database is corrupted. For this reason, Foal should provide an easy way to encrypt and decrypt refresh tokens.Issue 2
Once the refresh token is retrieved, in a later request for example, we still need to take a look at the Google API (or other providers API) to see how to get a new access token. This task could simply be handled by the framework.
Possible solution
Add three new methods
encryptRefreshToken
,decryptRefreshToken
andrefreshAndGetAccessToken
to each social service.The text was updated successfully, but these errors were encountered: