Skip to content

Commit 9af5862

Browse files
authored
Merge pull request #28 from lmammino/feature/refresh-token
Implemented decorator getNewAccessTokenUsingRefreshToken
2 parents 9f3e56b + fa0d8cb commit 9af5862

File tree

3 files changed

+57
-11
lines changed

3 files changed

+57
-11
lines changed

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,14 @@ fastify.register(oauthPlugin, {
3131
})
3232

3333
fastify.get('/login/facebook/callback', async function (request, reply) {
34-
const result = await this.getAccessTokenFromAuthorizationCodeFlow(request)
34+
const token = await this.getAccessTokenFromAuthorizationCodeFlow(request)
3535

36-
console.log(result.access_token)
36+
console.log(token.access_token)
3737

38-
reply.send({ access_token: result.access_token })
38+
// if later you need to refresh the token you can use
39+
// const newToken = await this.getNewAccessTokenUsingRefreshToken(token.refresh_token)
40+
41+
reply.send({ access_token: token.access_token })
3942
})
4043
```
4144

@@ -48,6 +51,17 @@ See [facebook example](./examples/facebook.js) for an example.
4851
This fastify plugin decorates the fastify instance with the [`simple-oauth2`](https://github.com/lelylan/simple-oauth2)
4952
instance.
5053

54+
## Utilities
55+
56+
This fastify plugin adds 2 utility decorators to your fastify instance:
57+
58+
- `getAccessTokenFromAuthorizationCodeFlow(request, callback)`: A function that uses the Authorization code flow to fetch an OAuth2 token using the data in the last request of the flow. If the callback is not passed it will return a promise. The object resulting from the callback call or the promise resolution is a *token response* object containing the following keys:
59+
- `access_token`
60+
- `refresh_token` (optional, only if the `offline scope` was originally requested)
61+
- `token_type` (generally `'bearer'`)
62+
- `expires_in` (number of seconds for the token to expire, e.g. `240000`)
63+
- `getNewAccessTokenUsingRefreshToken(refreshToken, params, callback)`: A function that takes a refresh token and retrieves a new *token response* object. This is generally useful with background processing workers to re-issue a new token when the original token has expired. The `params` argument is optional and it's an object that can be used to pass in extra parameters to the refresh request (e.g. a stricter set of scopes). If the callback is not passed this function will return a promise. The object resulting from the callback call or the promise resolution is a new *token response* object (see fields above).
64+
5165
## License
5266

5367
Licensed under [MIT](./LICENSE).

index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,25 @@ const oauthPlugin = fp(function (fastify, options, next) {
9494
getAccessTokenFromAuthorizationCodeFlowCallbacked(request, callback)
9595
}
9696

97+
function getNewAccessTokenUsingRefreshTokenCallbacked (refreshToken, params, callback) {
98+
const accessToken = fastify[name].accessToken.create({ refresh_token: refreshToken })
99+
accessToken.refresh(params, callback)
100+
}
101+
const getNewAccessTokenUsingRefreshTokenPromisified = promisify(getNewAccessTokenUsingRefreshTokenCallbacked)
102+
103+
function getNewAccessTokenUsingRefreshToken (refreshToken, params, callback) {
104+
if (!callback) {
105+
return getNewAccessTokenUsingRefreshTokenPromisified(refreshToken, params)
106+
}
107+
getNewAccessTokenUsingRefreshTokenCallbacked(refreshToken, params, callback)
108+
}
109+
97110
const oauth2 = oauth2Module.create(credentials)
98111

99112
if (startRedirectPath) {
100113
fastify.get(startRedirectPath, startRedirectHandler)
101114
fastify.decorate('getAccessTokenFromAuthorizationCodeFlow', getAccessTokenFromAuthorizationCodeFlow)
115+
fastify.decorate('getNewAccessTokenUsingRefreshToken', getNewAccessTokenUsingRefreshToken)
102116
}
103117

104118
try {

test.js

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,18 @@ function makeRequests (t, fastify) {
3131
expires_in: '240000'
3232
}
3333

34+
const RESPONSE_BODY_REFRESHED = {
35+
access_token: 'my-access-token-refreshed',
36+
refresh_token: 'my-refresh-token-refreshed',
37+
token_type: 'bearer',
38+
expires_in: '240000'
39+
}
40+
3441
const githubScope = nock('https://github.com')
3542
.post('/login/oauth/access_token', 'code=my-code&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fcallback&grant_type=authorization_code&client_id=my-client-id&client_secret=my-secret')
3643
.reply(200, RESPONSE_BODY)
44+
.post('/login/oauth/access_token', 'grant_type=refresh_token&refresh_token=my-refresh-token&client_id=my-client-id&client_secret=my-secret')
45+
.reply(200, RESPONSE_BODY_REFRESHED)
3746

3847
fastify.inject({
3948
method: 'GET',
@@ -42,7 +51,7 @@ function makeRequests (t, fastify) {
4251
t.error(err)
4352

4453
t.equal(responseEnd.statusCode, 200)
45-
t.strictSame(JSON.parse(responseEnd.payload), RESPONSE_BODY)
54+
t.strictSame(JSON.parse(responseEnd.payload), RESPONSE_BODY_REFRESHED)
4655

4756
githubScope.done()
4857

@@ -74,12 +83,18 @@ t.test('fastify-oauth2', t => {
7483
this.getAccessTokenFromAuthorizationCodeFlow(request, (err, result) => {
7584
if (err) throw err
7685

77-
const token = this.githubOAuth2.accessToken.create(result)
78-
reply.send({
79-
access_token: token.token.access_token,
80-
refresh_token: token.token.refresh_token,
81-
expires_in: token.token.expires_in,
82-
token_type: token.token.token_type
86+
// attempts to refresh the token
87+
this.getNewAccessTokenUsingRefreshToken(result.refresh_token, undefined, (err, result) => {
88+
if (err) throw err
89+
90+
const newToken = result
91+
92+
reply.send({
93+
access_token: newToken.token.access_token,
94+
refresh_token: newToken.token.refresh_token,
95+
expires_in: newToken.token.expires_in,
96+
token_type: newToken.token.token_type
97+
})
8398
})
8499
})
85100
})
@@ -109,7 +124,10 @@ t.test('fastify-oauth2', t => {
109124
fastify.get('/', function (request, reply) {
110125
return this.getAccessTokenFromAuthorizationCodeFlow(request)
111126
.then(result => {
112-
const token = this.githubOAuth2.accessToken.create(result)
127+
// attempts to refresh the token
128+
return this.getNewAccessTokenUsingRefreshToken(result.refresh_token)
129+
})
130+
.then(token => {
113131
return {
114132
access_token: token.token.access_token,
115133
refresh_token: token.token.refresh_token,

0 commit comments

Comments
 (0)