forked from nextauthjs/next-auth
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(provider): re-add state, expand protection provider options (nex…
…tauthjs#1184) * refactor: move OAuthCallbackError to errors file * refactor: improve pkce handling * feat(provider): re-introduce state to provider options * docs(provider): mention protection options "state" and "none" * docs(provider): document state property deprecation * fix: only add code_verifier param if protection is pkce * docs: explain state deprecation better * chore: unify string
- Loading branch information
1 parent
4855cdd
commit 659a486
Showing
10 changed files
with
148 additions
and
80 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,16 @@ | ||
import { createHash } from 'crypto' | ||
import { decode as jwtDecode } from 'jsonwebtoken' | ||
import oAuthClient from './client' | ||
import logger from '../../../lib/logger' | ||
class OAuthCallbackError extends Error { | ||
constructor (message) { | ||
super(message) | ||
this.name = 'OAuthCallbackError' | ||
this.message = message | ||
} | ||
} | ||
import { OAuthCallbackError } from '../../../lib/errors' | ||
|
||
export default async function oAuthCallback (req) { | ||
const { provider, csrfToken, pkce } = req.options | ||
const { provider, pkce } = req.options | ||
const client = oAuthClient(provider) | ||
|
||
if (provider.version?.startsWith('2.')) { | ||
// The "user" object is specific to the Apple provider and is provided on first sign in | ||
// e.g. {"name":{"firstName":"Johnny","lastName":"Appleseed"},"email":"[email protected]"} | ||
let { code, user, state } = req.query // eslint-disable-line camelcase | ||
// For OAuth 2.0 flows, check state returned and matches expected value | ||
// (a hash of the NextAuth.js CSRF token). | ||
// | ||
// Apple does not support state verification. | ||
if (provider.id !== 'apple') { | ||
const expectedState = createHash('sha256').update(csrfToken).digest('hex') | ||
if (state !== expectedState) { | ||
throw new OAuthCallbackError('Invalid state returned from OAuth provider') | ||
} | ||
} | ||
let { code, user } = req.query // eslint-disable-line camelcase | ||
|
||
if (req.method === 'POST') { | ||
try { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { createHash } from 'crypto' | ||
import logger from '../../../lib/logger' | ||
import { OAuthCallbackError } from '../../../lib/errors' | ||
|
||
/** | ||
* For OAuth 2.0 flows, if the provider supports state, | ||
* check if state matches the one sent on signin | ||
* (a hash of the NextAuth.js CSRF token). | ||
*/ | ||
export async function handleCallback (req, res) { | ||
const { csrfToken, provider, baseUrl, basePath } = req.options | ||
try { | ||
if (provider.protection !== 'state') { // Provider does not support state, nothing to do. | ||
return | ||
} | ||
|
||
const { state } = req.query | ||
const expectedState = createHash('sha256').update(csrfToken).digest('hex') | ||
|
||
logger.debug( | ||
'OAUTH_CALLBACK_PROTECTION', | ||
'Comparing received and expected state', | ||
{ state, expectedState } | ||
) | ||
if (state !== expectedState) { | ||
throw new OAuthCallbackError('Invalid state returned from OAuth provider') | ||
} | ||
} catch (error) { | ||
logger.error('STATE_ERROR', error) | ||
return res.redirect(`${baseUrl}${basePath}/error?error=OAuthCallback`) | ||
} | ||
} | ||
|
||
/** Adds CSRF token to the authorizationParams. */ | ||
export async function handleSignin (req, res) { | ||
const { provider, baseUrl, basePath, csrfToken } = req.options | ||
try { | ||
if (provider.protection !== 'state') { // Provider does not support state, nothing to do. | ||
return | ||
} | ||
|
||
if ('state' in provider) { | ||
logger.warn( | ||
'STATE_OPTION_DEPRECATION', | ||
'The `state` provider option is being replaced with `protection`. See the docs.' | ||
) | ||
} | ||
|
||
// A hash of the NextAuth.js CSRF token is used as the state | ||
const state = createHash('sha256').update(csrfToken).digest('hex') | ||
|
||
provider.authorizationParams = { ...provider.authorizationParams, state } | ||
logger.debug( | ||
'OAUTH_CALLBACK_PROTECTION', | ||
'Added state to authorization params', | ||
{ state } | ||
) | ||
} catch (error) { | ||
logger.error('SIGNIN_OAUTH_ERROR', error) | ||
return res.redirect(`${baseUrl}${basePath}/error?error=OAuthSignin`) | ||
} | ||
} | ||
|
||
export default { handleSignin, handleCallback } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters