Skip to content

Commit

Permalink
feat: forward signIn auth params to /authorize (#1149)
Browse files Browse the repository at this point in the history
* refactor: authorisation -> authorization

* feat: forward authorizationParams from signIn function

* refactor: take auth params as third argument

* docs: document signIn authorizationParams
  • Loading branch information
balazsorban44 committed Feb 1, 2021
1 parent 31bb2c3 commit cba149f
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ const _useSessionHook = (session) => {
}

// Client side method
export const signIn = async (provider, args = {}) => {
export const signIn = async (provider, args = {}, authorizationParams = {}) => {
const baseUrl = _apiBaseUrl()
const callbackUrl = args.callbackUrl ?? window.location
const providers = await getProviders()
Expand All @@ -257,6 +257,7 @@ export const signIn = async (provider, args = {}) => {
},
body: _encodedForm({
...args,
authorizationParams,
csrfToken: await getCsrfToken(),
callbackUrl: callbackUrl,
json: true
Expand Down
23 changes: 14 additions & 9 deletions src/server/lib/signin/oauth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@ import oAuthClient from '../oauth/client'
import { createHash } from 'crypto'
import logger from '../../../lib/logger'

export default async function oauth (provider, csrfToken) {
const { callbackUrl } = provider
export default async function getAuthorizationUrl (req) {
const { provider, csrfToken } = req.options

const client = oAuthClient(provider)
if (provider.version?.startsWith('2.')) {
// Handle OAuth v2.x
let url = client.getAuthorizeUrl({
redirect_uri: callbackUrl,
...provider.authorizationParams,
...req.body.authorizationParams,
redirect_uri: provider.callbackUrl,
scope: provider.scope,
// A hash of the NextAuth.js CSRF token is used as the state
state: createHash('sha256').update(csrfToken).digest('hex'),
...provider.authorizationParams
state: createHash('sha256').update(csrfToken).digest('hex')
})

// If the authorizationUrl specified in the config has query parameters on it
// make sure they are included in the URL we return.
//
// This is a fix for an open issue with the oAuthClient library we are using
// This is a fix for an open issue with the OAuthClient library we are using
// which inadvertantly strips them.
//
// https://github.com/ciaranj/node-oauth/pull/193
Expand All @@ -28,14 +30,17 @@ export default async function oauth (provider, csrfToken) {
url = url.replace(baseUrl, provider.authorizationUrl + '&')
}

logger.debug('GET_AUTHORIZATION_URL', url)
return url
}

try {
const oAuthToken = await client.getOAuthRequestToken(callbackUrl)
return `${provider.authorizationUrl}?oauth_token=${oAuthToken}`
const oAuthToken = await client.getOAuthRequestToken(provider.callbackUrl)
const url = `${provider.authorizationUrl}?oauth_token=${oAuthToken}`
logger.debug('GET_AUTHORIZATION_URL', url)
return url
} catch (error) {
logger.error('GET_AUTHORISATION_URL_ERROR', error)
logger.error('GET_AUTHORIZATION_URL_ERROR', error)
throw error
}
}
9 changes: 4 additions & 5 deletions src/server/routes/signin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import oAuthSignin from '../lib/signin/oauth'
import getAuthorizationUrl from '../lib/signin/oauth'
import emailSignin from '../lib/signin/email'
import logger from '../../lib/logger'

Expand All @@ -9,8 +9,7 @@ export default async function signin (req, res) {
baseUrl,
basePath,
adapter,
callbacks,
csrfToken
callbacks
} = req.options

if (!provider.type) {
Expand All @@ -19,8 +18,8 @@ export default async function signin (req, res) {

if (provider.type === 'oauth' && req.method === 'POST') {
try {
const oAuthSigninUrl = await oAuthSignin(provider, csrfToken)
return res.redirect(oAuthSigninUrl)
const authorizazionUrl = await getAuthorizationUrl(req)
return res.redirect(authorizazionUrl)
} catch (error) {
logger.error('SIGNIN_OAUTH_ERROR', error)
return res.redirect(`${baseUrl}${basePath}/error?error=OAuthSignin`)
Expand Down
2 changes: 1 addition & 1 deletion www/docs/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ These errors are displayed on the terminal.

### Signin / Callback

#### GET_AUTHORISATION_URL_ERROR
#### GET_AUTHORIZATION_URL_ERROR

#### SIGNIN_OAUTH_ERROR

Expand Down
19 changes: 19 additions & 0 deletions www/docs/getting-started/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,25 @@ e.g.

The URL must be considered valid by the [redirect callback handler](/configuration/callbacks#redirect). By default it requires the URL to be an absolute URL at the same hostname, or else it will redirect to the homepage. You can define your own redirect callback to allow other URLs, including supporting relative URLs.

#### Additional params

It is also possible to pass additional parameters to the `/authorize` endpoint through the third argument of `signIn()`.

See the [Authorization Request OIDC spec](https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest) for some ideas.

e.g.

* `signIn("identity-server4", null, { prompt: "login" })` *always ask the user to reauthenticate*
* `signIn("auth0", null, { login_hint: "info@example.com" })` *hints the e-mail address to the provider*

:::note
You can also set these parameters through [`provider.authorizationParams`](/configuration/providers#oauth-provider-options).
:::

:::note
The following parameters are always overridden: `redirect_uri`, `scope`, `state`
:::

---

## signOut()
Expand Down

0 comments on commit cba149f

Please sign in to comment.