Created
April 6, 2021 16:24
-
-
Save simonagren/561bd3fb3da35bbb1d72310ee23c54ec to your computer and use it in GitHub Desktop.
Quick example MSAL Node
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
/** | |
* Gets an access token for the user using the on-behalf-of flow | |
* @param authHeader - The Authorization header value containing a JWT bearer token | |
* @returns {Promise<string | null>} - Returns the access token if successful, null if not | |
*/ | |
export async function getAccessTokenOnBehalfOf(req: Request, res: Response): Promise<void> { | |
// The token has already been validated, just grab it and the other values from the query string | |
const ssoToken: string = req.headers.authorization!.split(' ')[1]; | |
const clientId: string = req.body.clientId!.toString(); | |
const graphScopes: string[] = req.body.scopes!.toString().split(','); | |
// Get tenantId from the SSO Token | |
const tenantId: string = jwt_decode<any>(ssoToken).tid; | |
const clientSecret: string = process.env.APP_SECRET!; | |
// Create an MSAL client | |
const msalClient = new msal.ConfidentialClientApplication({ | |
auth: { | |
clientId: clientId, | |
clientSecret: clientSecret | |
} | |
}); | |
try { | |
const result = await msalClient.acquireTokenOnBehalfOf({ | |
authority: `https://login.microsoftonline.com/${tenantId}`, | |
oboAssertion: ssoToken, | |
scopes: graphScopes, | |
skipCache: true | |
}); | |
res.json({ access_token: result?.accessToken }); | |
} catch (error) { | |
if (error.errorCode === 'invalid_grant' || error.errorCode === 'interaction_required') { | |
// This is expected if it's the user's first time running the app ( user must consent ) or the admin requires MFA | |
res.status(403).json({ error: 'consent_required' }); // This error triggers the consent flow in the client. | |
} else { | |
// Unknown error | |
res.status(500).json({ error: error.message }); | |
} | |
} |
Great. It's always something small ;)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks. I just got this working. It turned out I changed my graph scopes and the value I was passing into acquireTokenOnBehalfOf() was incorrect. Thus the need to prompt for consent again.