A place to share technical learnings, etc.
aws | jekyll | github | apigateway | serverless | ad | powershell | windows | webdev | nodejs | terraform | consul | nomad | jenkins | traefik | azuread | azure | nextjs |
AWS’ API Gateway v2 (aka HTTP APIs) launched in December 2019, and came with a built-in ability to add JWT authorizers to endpoints. We use AzureAD as our Auth vendor, so I’ve been waiting for a chance to try this out. Finally got an opportunity.
I’m assuming you have a functional AzureAD application - I have an existing React app - so I’m just going to cover the pieces I needed to add/modify to get the AzureAD integration working.
This ended up being one of the most difficult parts.
At this point, your application should be able to request a token to call the AzureAD API.
I had an existing Lambda function that I used for this, but if necessary, build a Lambda function and ensure it works and returns something to the caller so you’re able to test things out.
At this point, you should be able to test your API with Postman. You’ll have to obtain an access token good for your API.
I use https://www.npmjs.com/package/react-aad-msal in my React applications, but I ran into an issue where even when I specified the scope for my API Application in my authProvider.js file, the token I was getting was still only good for the MS Graph API. Decoding the Access Token with JWT.io showed an invalid signature - apparently access tokens for MS Graph API include a nonce value that makes the token not validate correctly against the public key (https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/521) - learn something new everyday. Big shout out to Eric Johnson@AWS for helping me track this down.
I ended up adding some code to my React project to dump an access token to the console, and used react-aad-msal’s ability to call into the underlying msal library to make this happen:
var tokenRequest = {
scopes: ["api://<MY API's APP REGISRATION/CLIENTID>/<MY API's SCOPE>"]
};
//call in and get a token for our api
let token = await props.provider.acquireTokenSilent(tokenRequest)
console.log(token.accessToken);
Once you have an access token valid for your API (you can pretty easily decode and check this with jwt.io), you should be able to use Postman to access the API - just set the Authorization to Bearer token and paste your access token into the token section.
To be able to use this in a browser-based app which was my goal, there’s some additional configuration required.
This should allow you to access the API from the browser using CORS with something like:
let response = await fetch("https://YOURAPI.execute-api.us-west-2.amazonaws.com", {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + token.accessToken
},
});
var data = await response.json();
HUZZAH!
This vastly simplified API Gateway v2 is really a gamechanger for us - the previous API Gateway worked well, but it was WAYYYY too complicated. And the ability to do JWT auth easily like this - beautiful. Well done AWS.
tags: aws - azuread