Skip to content

Commit 32a3bab

Browse files
authored
Merge pull request #242 from scientist-softserv/232-refresh-token
232 refresh token
2 parents 35fc585 + 8971b24 commit 32a3bab

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

pages/api/auth/[...nextauth].js

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import NextAuth from 'next-auth'
2+
import axios from 'axios'
3+
// TODO(alishaevn): use the api value from https://github.com/assaydepot/rx/issues/21497 in the next phase
4+
import { EXPIRATION_DURATION } from '../../../utils'
25

36
// For more information on each option (and a full list of options) go to: https://next-auth.js.org/configuration/options
47
const authOptions = {
@@ -28,11 +31,22 @@ const authOptions = {
2831
callbacks: {
2932
async jwt({ token, account, user }) {
3033
// Triggered on the initial sign in
31-
// TODO(alishaevn): account for the refresh token
3234
if (account && user) {
33-
token.accessToken = account.access_token
35+
return {
36+
accessToken: account.access_token,
37+
accessTokenExpires: Date.now() + EXPIRATION_DURATION,
38+
refreshToken: account.refresh_token,
39+
user,
40+
}
41+
}
42+
43+
// Return previous token if the access token has not expired yet
44+
if (token.accessTokenExpires && (Date.now() < token.accessTokenExpires)) {
45+
return token
3446
}
35-
return token
47+
48+
// Access token has expired, try to update it
49+
return refreshAccessToken(token)
3650
},
3751
async session({ session, token }) {
3852
// Send additional properties to the client
@@ -42,4 +56,42 @@ const authOptions = {
4256
}
4357
}
4458

59+
/**
60+
* Takes a token, and returns a new token with an updated `accessToken`.
61+
* If an error occurs, returns the old token and an error property
62+
*/
63+
const refreshAccessToken = async (token) => {
64+
try {
65+
const url = `https://${process.env.NEXT_PUBLIC_PROVIDER_NAME}.scientist.com/oauth/token`
66+
const encodedString = Buffer.from(`${process.env.CLIENT_ID}:${process.env.CLIENT_SECRET}`).toString('base64')
67+
const params = new URLSearchParams({
68+
grant_type: 'refresh_token',
69+
refresh_token: token.refreshToken,
70+
})
71+
72+
const response = await axios.post(url, params, {
73+
headers: {
74+
'Authorization': `Basic ${encodedString}`,
75+
},
76+
})
77+
const refreshedTokens = response.data
78+
79+
if (response.status !== 200) {
80+
throw refreshedTokens
81+
}
82+
83+
return {
84+
...token,
85+
accessToken: refreshedTokens.access_token,
86+
accessTokenExpires: Date.now() + EXPIRATION_DURATION,
87+
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken, // Fall back to the old refresh token
88+
}
89+
} catch (error) {
90+
return {
91+
...token,
92+
error: 'RefreshAccessTokenError',
93+
}
94+
}
95+
}
96+
4597
export default NextAuth(authOptions)

utils/constants.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,8 @@ export const NAVIGATION_LINKS = [
103103
// change this to '/services' to have this link to a page for an individual service.
104104
// if you choose to go this route, you can update the content for the service's page at pages/services/[ware].js
105105
export const FEATURED_SERVICE_PATH = '/requests/new'
106+
107+
// TODO(alishaevn): use the api value from https://github.com/assaydepot/rx/issues/21497 in the next phase
108+
// this amount, listed in milliseconds, represents when the access token will expire
109+
// the default is 1 week
110+
export const EXPIRATION_DURATION = 604800000

0 commit comments

Comments
 (0)