Summary
I'll be covering the usage of the RFC 7523 authorization grant type in this post. I'll create a server-side implementation as a Google Cloud Function and a simple client in Node.js.
Architecture
The implementation consists of a Google Cloud Function that is triggered on an HTTP POST request. The request has a form-urlencoded body consisting of the grant_type parameter and an assertion with the JSON web token (JWT) - per the RFC. The response is a JSON object consisting of the token type, bearer token, and the unencoded version of the original JWT received. That last item isn't required, but I included it to aid in troubleshooting.
Server-side Snippet
As discussed, the server is implemented as a GCF. For a Node implementation, that consists of an Express server. The express-jwt middleware is used to implement the JWT handling.
app.use(expressJwt({ secret: sharedKey, issuer: issuer, audience: audience, algorithms: ['HS256', 'HS384', 'HS512'], requestProperty: 'token', getToken: (req) => { return req.body.assertion; } })); app.post('/rfc7523', (req, res) => { if (req.token) { console.log(`Received token: ${JSON.stringify(req.token)}`); const alg = 'HS512' const payload = { "iss": 'oauth issuer', "sub": 'oauth authority', "aud": 'm2mclient', "exp": Math.round(Date.now()/1000 + 3) //3 second expiration }; const accessToken = jwt.sign(payload, privateKey, {algorithm: alg}); res.status(200) .json({ token_type: 'bearer', rec_token: req.token, access_token: accessToken }); } else { res.status(400).json({error: 'no token found'}); } });
Client-side Snippet
(async () => { const payload = { "iss": issuer, "sub": subject, "aud": audience, "exp": Math.round(Date.now()/1000 + 3) //3 second expiration }; const alg = 'HS512' const token = jwt.sign(payload, sharedKey, {algorithm: alg}); const authGrant = encodeURI('urn:ietf:params:oauth:grant-type:jwt-bearer'); const response = await fetch(url, { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: `grant_type=${authGrant}&assertion=${token}` }); const json = await response.json(); console.log(`Results: ${JSON.stringify(json, null, 4)}`); })();
Results
Results: { ... "access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJvYXV0aCBpc3 - abbreviated" }
Source
Copyright ©1993-2024 Joey E Whelan, All rights reserved.