Skip to content

Instantly share code, notes, and snippets.

@simonagren
Created April 6, 2021 16:24
Show Gist options
  • Save simonagren/561bd3fb3da35bbb1d72310ee23c54ec to your computer and use it in GitHub Desktop.
Save simonagren/561bd3fb3da35bbb1d72310ee23c54ec to your computer and use it in GitHub Desktop.
Quick example MSAL Node
/**
* 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 });
}
}
@coreyroth
Copy link

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.

@simonagren
Copy link
Author

Great. It's always something small ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment