mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f899d7bb04 | ||
|
|
e36646ce7f | ||
|
|
f3d36a74c9 | ||
|
|
4e11c9c36e | ||
|
|
0a7ac36584 | ||
|
|
fc4850f354 | ||
|
|
6e9a8d2074 | ||
|
|
c712d7da07 | ||
|
|
5183181d1c | ||
|
|
b024f89ba8 | ||
|
|
fbbe516b9a | ||
|
|
d48a3fd948 | ||
|
|
86f0c53bd3 | ||
|
|
7f6cc2048b | ||
|
|
b2829f6384 | ||
|
|
67c5041860 | ||
|
|
33df9e3132 | ||
|
|
602bc28a45 | ||
|
|
5a7a494701 | ||
|
|
9fa82cedbd | ||
|
|
b0408284b8 |
36
.github/workflows/npm-publish.yml
vendored
Normal file
36
.github/workflows/npm-publish.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# Publishes module to registry when a new release is created.
|
||||
#
|
||||
# The following secrets need to be configured for this workflow:
|
||||
#
|
||||
# * NPM_TOKEN - Auth token from npmjs.com
|
||||
|
||||
name: Publish to NPM
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
|
||||
publish-npm:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- run: npm ci
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-auth",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-auth",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"description": "An authentication library for Next.js",
|
||||
"repository": "https://github.com/iaincollins/next-auth.git",
|
||||
"author": "Iain Collins <me@iaincollins.com>",
|
||||
|
||||
@@ -15,4 +15,4 @@ const css = fs.readFileSync(pathToCss, 'utf8')
|
||||
const cssWithEscapedQuotes = css.replace(/"/gm, '\\"')
|
||||
const js = `module.exports = function() { return "${cssWithEscapedQuotes}" }`
|
||||
|
||||
fs.writeFileSync(pathToCssJs, js)
|
||||
fs.writeFileSync(pathToCssJs, js)
|
||||
|
||||
@@ -3,41 +3,47 @@
|
||||
import { useState, useEffect, useContext, createContext, createElement } from 'react'
|
||||
import logger from '../lib/logger'
|
||||
|
||||
// Note: In calls to fetch() from universal methods, all cookies are passed
|
||||
// through from the browser, when the server makes the HTTP request, so that
|
||||
// it can authenticate as the browser.
|
||||
const __NEXTAUTH = {
|
||||
site: '',
|
||||
basePath: '/api/auth',
|
||||
clientMaxAge: 0 // e.g. 0 == disabled, 60 == 60 seconds
|
||||
}
|
||||
|
||||
// These can be overridden with NEXTAUTH_ env vars in next.config.js
|
||||
// e.g. process.env.NEXTAUTH_SITE
|
||||
const NEXTAUTH_DEFAULT_BASE_URL_COOKIE_NAME = 'next-auth.base-url'
|
||||
const NEXTAUTH_DEFAULT_SITE = ''
|
||||
const NEXTAUTH_DEFAULT_BASE_PATH = '/api/auth'
|
||||
const NEXTAUTH_DEFAULT_CLIENT_MAXAGE = 0 // e.g. 0 == disabled, 60 == 60 seconds
|
||||
let __NEXTAUTH_EVENT_LISTENER_ADDED = false
|
||||
|
||||
let NEXTAUTH_EVENT_LISTENER_ADDED = false
|
||||
// Method to set options. The documented way is to use the provider, but this
|
||||
// method is being left in as an alternative, that will be helpful if/when we
|
||||
// expose a vanilla JavaScript version that doesn't depend on React.
|
||||
const setOptions = ({
|
||||
site,
|
||||
basePath,
|
||||
clientMaxAge
|
||||
} = {}) => {
|
||||
if (site) { __NEXTAUTH.site = site }
|
||||
if (basePath) { __NEXTAUTH.basePath = basePath }
|
||||
if (clientMaxAge) { __NEXTAUTH.clientMaxAge = clientMaxAge }
|
||||
}
|
||||
|
||||
// Universal method (client + server)
|
||||
const getSession = async ({ req } = {}) => {
|
||||
const baseUrl = _baseUrl({ req })
|
||||
const baseUrl = _baseUrl()
|
||||
const options = req ? { headers: { cookie: req.headers.cookie } } : {}
|
||||
const session = await _fetchData(`${baseUrl}/session`, options)
|
||||
_sendMessage({ event: 'session', data: { triggeredBy: 'getSession' } })
|
||||
_sendMessage({ event: 'session', data: { trigger: 'getSession' } })
|
||||
return session
|
||||
}
|
||||
|
||||
// Universal method (client + server)
|
||||
const getProviders = async ({ req } = {}) => {
|
||||
const baseUrl = _baseUrl({ req })
|
||||
const options = req ? { headers: { cookie: req.headers.cookie } } : {}
|
||||
return _fetchData(`${baseUrl}/providers`, options)
|
||||
const getProviders = async () => {
|
||||
const baseUrl = _baseUrl()
|
||||
return _fetchData(`${baseUrl}/providers`)
|
||||
}
|
||||
|
||||
// Universal method (client + server)
|
||||
const getCsrfToken = async ({ req } = {}) => {
|
||||
const baseUrl = _baseUrl({ req })
|
||||
const options = req ? { headers: { cookie: req.headers.cookie } } : {}
|
||||
const data = await _fetchData(`${baseUrl}/csrf`, options)
|
||||
return data.csrfToken
|
||||
const getCsrfToken = async () => {
|
||||
const baseUrl = _baseUrl()
|
||||
const data = await _fetchData(`${baseUrl}/csrf`)
|
||||
return data && data.csrfToken ? data.csrfToken : null
|
||||
}
|
||||
|
||||
// Context to store session data globally
|
||||
@@ -57,8 +63,7 @@ const useSession = (session) => {
|
||||
|
||||
// Internal hook for getting session from the api.
|
||||
const useSessionData = (session) => {
|
||||
const clientMaxAge = (process.env.NEXTAUTH_CLIENT_MAXAGE || NEXTAUTH_DEFAULT_CLIENT_MAXAGE) * 1000
|
||||
|
||||
const clientMaxAge = __NEXTAUTH.clientMaxAge * 1000
|
||||
const [data, setData] = useState(session)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const _getSession = async (sendEvent = true) => {
|
||||
@@ -68,17 +73,17 @@ const useSessionData = (session) => {
|
||||
|
||||
// Send event to trigger other tabs to update (unless sendEvent is false)
|
||||
if (sendEvent) {
|
||||
_sendMessage({ event: 'session', data: { triggeredBy: 'useSessionData' } })
|
||||
_sendMessage({ event: 'session', data: { trigger: 'useSessionData' } })
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && NEXTAUTH_EVENT_LISTENER_ADDED === false) {
|
||||
NEXTAUTH_EVENT_LISTENER_ADDED = true
|
||||
if (typeof window !== 'undefined' && __NEXTAUTH_EVENT_LISTENER_ADDED === false) {
|
||||
__NEXTAUTH_EVENT_LISTENER_ADDED = true
|
||||
window.addEventListener('storage', async (event) => {
|
||||
if (event.key === 'nextauth.message') {
|
||||
const message = JSON.parse(event.newValue)
|
||||
if (message.event && message.event === 'session' && message.data) {
|
||||
// Fetch new session data but tell it not to fire an event to
|
||||
// avoid an infinate loop.
|
||||
// avoid an infinite loop.
|
||||
//
|
||||
// Note: We could pass session data through and do something like
|
||||
// `setData(message.data)` but that causes problems depending on
|
||||
@@ -159,18 +164,18 @@ const signout = async (args) => {
|
||||
}
|
||||
const res = await fetch(`${baseUrl}/signout`, options)
|
||||
|
||||
_sendMessage({ event: 'session', data: { triggeredBy: 'signout' } })
|
||||
_sendMessage({ event: 'session', data: { trigger: 'signout' } })
|
||||
|
||||
window.location = res.url ? res.url : callbackUrl
|
||||
}
|
||||
|
||||
// Provider to wrap the app in to make session data available globally
|
||||
const Provider = ({ children, session }) => {
|
||||
const value = useSession(session)
|
||||
return createElement(SessionContext.Provider, { value }, children)
|
||||
const Provider = ({ children, session, options }) => {
|
||||
setOptions(options)
|
||||
return createElement(SessionContext.Provider, { value: useSession(session) }, children)
|
||||
}
|
||||
|
||||
const _fetchData = async (url, options) => {
|
||||
const _fetchData = async (url, options = {}) => {
|
||||
try {
|
||||
const res = await fetch(url, options)
|
||||
const data = await res.json()
|
||||
@@ -181,44 +186,7 @@ const _fetchData = async (url, options) => {
|
||||
}
|
||||
}
|
||||
|
||||
const _baseUrl = ({ req } = {}) => {
|
||||
if (req) {
|
||||
// Server Side
|
||||
// If we have a 'req' object are running sever side, so we should grab the
|
||||
// base URL from cookie that is set by the API route - which is how config
|
||||
// is shared automatically between the API route and the client.
|
||||
const cookies = req ? _parseCookies(req.headers.cookie) : null
|
||||
const baseUrlCookieName = process.env.NEXTAUTH_BASE_URL_COOKIE_NAME || NEXTAUTH_DEFAULT_BASE_URL_COOKIE_NAME
|
||||
const cookieValue = cookies[`__Secure-${baseUrlCookieName}`] || cookies[baseUrlCookieName]
|
||||
const [baseUrl] = cookieValue ? cookieValue.split('|') : [null]
|
||||
return baseUrl
|
||||
} else {
|
||||
// Client Side
|
||||
// Note: 'site' is empty by default; URL is normally relative.
|
||||
const site = process.env.NEXTAUTH_SITE || NEXTAUTH_DEFAULT_SITE
|
||||
const basePath = process.env.NEXTAUTH_BASE_PATH || NEXTAUTH_DEFAULT_BASE_PATH
|
||||
return `${site}${basePath}`
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/felixfong227/simple-cookie-parser/blob/master/index.js
|
||||
const _parseCookies = (string) => {
|
||||
if (!string) { return {} }
|
||||
try {
|
||||
const object = {}
|
||||
const a = string.split(';')
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
const b = a[i].split('=')
|
||||
if (b[0].length > 1 && b[1]) {
|
||||
object[b[0].trim()] = decodeURIComponent(b[1])
|
||||
}
|
||||
}
|
||||
return object
|
||||
} catch (error) {
|
||||
logger.error('CLIENT_COOKIE_PARSE_ERROR', error)
|
||||
return {}
|
||||
}
|
||||
}
|
||||
const _baseUrl = () => `${__NEXTAUTH.site}${__NEXTAUTH.basePath}`
|
||||
|
||||
const _encodedForm = (formData) => {
|
||||
return Object.keys(formData).map((key) => {
|
||||
@@ -233,6 +201,10 @@ const _sendMessage = (message) => {
|
||||
}
|
||||
|
||||
export default {
|
||||
// Call config() from _app.js to set options globally in the app.
|
||||
// You need to set at least the site name to use server side calls.
|
||||
options: setOptions,
|
||||
setOptions,
|
||||
// Some methods are exported with more than one name. This provides
|
||||
// flexibility over how they can be invoked and compatibility with earlier
|
||||
// releases (going back to v1 and earlier v2 beta releases).
|
||||
|
||||
@@ -7,4 +7,4 @@ import path from 'path'
|
||||
const pathToCss = path.join(__dirname, '/index.css')
|
||||
const css = fs.readFileSync(pathToCss, 'utf8')
|
||||
|
||||
export default () => css
|
||||
export default () => css
|
||||
|
||||
@@ -11,7 +11,7 @@ const logger = {
|
||||
}
|
||||
},
|
||||
debug: (debugCode, ...text) => {
|
||||
if (process && process.env && process.env._NEXT_AUTH_DEBUG) {
|
||||
if (process && process.env && process.env._NEXTAUTH_DEBUG) {
|
||||
console.log(
|
||||
`[next-auth][debug][${debugCode}]`,
|
||||
text
|
||||
|
||||
@@ -4,11 +4,11 @@ export default (options) => {
|
||||
name: 'Auth0',
|
||||
type: 'oauth',
|
||||
version: '2.0',
|
||||
params: { grant_type: 'authorization_code', response_type: 'code' },
|
||||
params: { grant_type: 'authorization_code' },
|
||||
scope: 'openid email profile',
|
||||
accessTokenUrl: `https://${options.subdomain}.auth0/oauth/token`,
|
||||
authorizationUrl: `https://${options.subdomain}.auth0.com/authorize?`,
|
||||
profileUrl: `http://${options.subdomain}.auth0.com/userinfo`,
|
||||
accessTokenUrl: `https://${options.domain}/oauth/token`,
|
||||
authorizationUrl: `https://${options.domain}/authorize?response_type=code`,
|
||||
profileUrl: `https://${options.domain}/userinfo`,
|
||||
profile: (profile) => {
|
||||
return {
|
||||
id: profile.sub,
|
||||
|
||||
29
src/providers/battlenet.js
Normal file
29
src/providers/battlenet.js
Normal file
@@ -0,0 +1,29 @@
|
||||
export default (options) => {
|
||||
const { region } = options
|
||||
return {
|
||||
id: 'battlenet',
|
||||
name: 'Battle.net',
|
||||
type: 'oauth',
|
||||
version: '2.0',
|
||||
scope: 'openid',
|
||||
params: { grant_type: 'authorization_code' },
|
||||
accessTokenUrl:
|
||||
region === 'CN'
|
||||
? 'https://www.battlenet.com.cn/oauth/token'
|
||||
: `https://${region}.battle.net/oauth/token`,
|
||||
authorizationUrl:
|
||||
region === 'CN'
|
||||
? 'https://www.battlenet.com.cn/oauth/authorize'
|
||||
: `https://${region}.battle.net/oauth/authorize`,
|
||||
profileUrl: 'https://us.battle.net/oauth/userinfo',
|
||||
profile: (profile) => {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.battletag,
|
||||
email: null,
|
||||
image: null
|
||||
}
|
||||
},
|
||||
...options
|
||||
}
|
||||
}
|
||||
23
src/providers/cognito.js
Normal file
23
src/providers/cognito.js
Normal file
@@ -0,0 +1,23 @@
|
||||
export default (options) => {
|
||||
const { domain } = options
|
||||
return {
|
||||
id: 'cognito',
|
||||
name: 'Cognito',
|
||||
type: 'oauth',
|
||||
version: '2.0',
|
||||
scope: 'openid profile email',
|
||||
params: { grant_type: 'authorization_code' },
|
||||
accessTokenUrl: `https://${domain}/oauth2/token`,
|
||||
authorizationUrl: `https://${domain}/oauth2/authorize?response_type=code`,
|
||||
profileUrl: `https://${domain}/oauth2/userInfo`,
|
||||
profile: (profile) => {
|
||||
return {
|
||||
id: profile.sub,
|
||||
name: profile.username,
|
||||
email: profile.email,
|
||||
image: null
|
||||
}
|
||||
},
|
||||
...options
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,11 @@ import Auth0 from './auth0'
|
||||
import Apple from './apple'
|
||||
import Box from './box'
|
||||
import Credentials from './credentials'
|
||||
import BattleNet from './battlenet'
|
||||
import Cognito from './cognito'
|
||||
import Discord from './discord'
|
||||
import Email from './email'
|
||||
import Facebook from './facebook' // @TODO
|
||||
import Facebook from './facebook'
|
||||
import GitHub from './github'
|
||||
import GitLab from './gitlab'
|
||||
import Google from './google'
|
||||
@@ -21,6 +23,8 @@ export default {
|
||||
Apple,
|
||||
Box,
|
||||
Credentials,
|
||||
BattleNet,
|
||||
Cognito,
|
||||
Discord,
|
||||
Email,
|
||||
Facebook,
|
||||
|
||||
@@ -89,15 +89,6 @@ export default async (req, res, userSuppliedOptions) => {
|
||||
secure: useSecureCookies
|
||||
}
|
||||
},
|
||||
baseUrl: {
|
||||
name: `${cookiePrefix}next-auth.base-url`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: useSecureCookies
|
||||
}
|
||||
},
|
||||
csrfToken: {
|
||||
// Default to __Host- for CSRF token for additional protection if using useSecureCookies
|
||||
// NB: The `__Host-` prefix is stricter than the `__Secure-` prefix.
|
||||
@@ -180,24 +171,6 @@ export default async (req, res, userSuppliedOptions) => {
|
||||
cookie.set(res, cookies.csrfToken.name, newCsrfTokenCookie, cookies.csrfToken.options)
|
||||
}
|
||||
|
||||
// Set canonical site name + API route in a cookie to facilitate passing configuration
|
||||
// to the NextAuth client. There are potential security considerations around this
|
||||
// relating to trying to prevent attackers from exploiting this by setting this cookie
|
||||
// on the client first if they can get control of a sub domain or exploit a XSS
|
||||
// vulnerability, but this approach attempts to mitgate that by always verifying
|
||||
// the cookie and updating it if fails the verification check.
|
||||
let setUrlPrefixCookie = true
|
||||
if (req.cookies[cookies.baseUrl.name]) {
|
||||
const [baseUrlValue, baseUrlHash] = req.cookies[cookies.baseUrl.name].split('|')
|
||||
// If the hash on the cookie is verified, then we must have set the cookie and don't need to update it
|
||||
if (baseUrlValue === baseUrl && baseUrlHash === createHash('sha256').update(`${baseUrlValue}${secret}`).digest('hex')) { setUrlPrefixCookie = false }
|
||||
}
|
||||
// If the cookie is not set already (or if it is set, but failed verification) set header to update the cookie
|
||||
if (setUrlPrefixCookie) {
|
||||
const newUrlPrefixCookie = `${baseUrl}|${createHash('sha256').update(`${baseUrl}${secret}`).digest('hex')}`
|
||||
cookie.set(res, cookies.baseUrl.name, newUrlPrefixCookie, cookies.baseUrl.options)
|
||||
}
|
||||
|
||||
// User provided options are overriden by other options,
|
||||
// except for the options with special handling above
|
||||
const options = {
|
||||
@@ -227,7 +200,7 @@ export default async (req, res, userSuppliedOptions) => {
|
||||
}
|
||||
|
||||
// If debug enabled, set ENV VAR so that logger logs debug messages
|
||||
if (options.debug === true) { process.env._NEXT_AUTH_DEBUG = true }
|
||||
if (options.debug === true) { process.env._NEXTAUTH_DEBUG = true }
|
||||
|
||||
// Get / Set callback URL based on query param / cookie + validation
|
||||
options.callbackUrl = await callbackUrlHandler(req, res, options)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import signin from './signin'
|
||||
import signout from './signout'
|
||||
import verifyRequest from './verify-request'
|
||||
|
||||
@@ -7,16 +7,16 @@ Callbacks are asynchronous functions you can use to control what happens when an
|
||||
|
||||
Callbacks are extremely powerful, especially in scenarios involving JSON Web Tokens as they allow you to implement access controls without a database and to integrate with external databases or APIs.
|
||||
|
||||
### Example
|
||||
|
||||
You can specify a handler for any of the callbacks below.
|
||||
|
||||
#### How to use the callback option
|
||||
|
||||
```js
|
||||
```js title="pages/api/auth/[...nextauth.js]"
|
||||
callbacks: {
|
||||
signin: async (profile, account, metadata) => { },
|
||||
redirect: async (url, baseUrl) => { },
|
||||
session: async (session, token) => { },
|
||||
jwt: async (token) => { }
|
||||
jwt: async (token, oAuthProfile) => { }
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
23
www/docs/configuration/events.md
Normal file
23
www/docs/configuration/events.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
id: events
|
||||
title: Events
|
||||
---
|
||||
|
||||
Events are asynchronous functions that do not return a response, they are useful for audit logging.
|
||||
|
||||
### Example
|
||||
|
||||
You can specify a handler for any of these events below - e.g. for debugging or to create an audit log.
|
||||
|
||||
```js title="pages/api/auth/[...nextauth.js]"
|
||||
events: {
|
||||
signin: async (message) => { /* on successful sign in */ },
|
||||
signout: async (message) => { /* on signout */ },
|
||||
createUser: async (message) => { /* user created */ },
|
||||
linkAccount: async (message) => { /* account linked to a user */ },
|
||||
session: async (message) => { /* session is active */ },
|
||||
error: async (message) => { /* error in authentication flow */ }
|
||||
}
|
||||
```
|
||||
|
||||
The content of the message object varies depending on the flow (e.g. OAuth or Email authentication flow, JWT or database sessions, etc), but typically contains a user object and/or contents of the JSON Web Token and other information relevent to the event.
|
||||
@@ -289,20 +289,16 @@ Advanced options are passed the same way as basic options, but may have complex
|
||||
|
||||
This option allows you to specify a different base path if you don't want to use `/api/auth` for some reason.
|
||||
|
||||
If you set this option you **must** also specify the same value in the `NEXTAUTH_BASE_PATH` environment variable in `next.config.js` so that the client knows how to contact the server:
|
||||
If you set this option you **must** also configure it along with the `site` property in `pages/_app.js`
|
||||
|
||||
```js title="next.config.js"
|
||||
module.exports = {
|
||||
env: {
|
||||
NEXTAUTH_BASE_PATH: '/api/my-custom-auth-route',
|
||||
},
|
||||
}
|
||||
```js title="pages/_app.js"
|
||||
import { config } from 'next-auth/client'
|
||||
config({
|
||||
site: process.env.SITE, // e.g. 'http://localhost:3000'
|
||||
basePath: process.env.BASE_PATH // e.g. '/api/some-other-route-name'
|
||||
})
|
||||
```
|
||||
|
||||
This is required because the NextAuth.js API route is a separate codepath to the NextAuth.js Client.
|
||||
|
||||
As long as you also specify this option in an environment variable, the client will be able to pick up any subsequent configuration from the server, but if you do not set in both it the NextAuth.js Client will not work.
|
||||
|
||||
---
|
||||
|
||||
### adapter
|
||||
@@ -379,15 +375,6 @@ cookies: {
|
||||
secure: true
|
||||
}
|
||||
},
|
||||
baseUrl: {
|
||||
name: `__Secure-next-auth.base-url`,
|
||||
options: {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
secure: true
|
||||
}
|
||||
},
|
||||
csrfToken: {
|
||||
name: `__Host-next-auth.csrf-token`,
|
||||
options: {
|
||||
@@ -403,38 +390,3 @@ cookies: {
|
||||
:::warning
|
||||
Changing the cookie options may introduce security flaws into your application and may break NextAuth.js integration now or in a future update. Using this option is not recommended.
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
### Client Max Age
|
||||
|
||||
* **Default value**: `0`
|
||||
* **Required**: *No*
|
||||
|
||||
#### Description
|
||||
|
||||
By default the NextAuth.js client will use whatever cached session object it has and will not not re-check the current session if using the `useSession()` hook.
|
||||
|
||||
You can change this behaviour and force it to periodically sync the session state by setting a `NEXTAUTH_CLIENT_MAXAGE` environment variable.
|
||||
|
||||
```js title="next.config.js"
|
||||
module.exports = {
|
||||
env: {
|
||||
NEXTAUTH_CLIENT_MAXAGE: 60, // Will re-check session every 60 seconds
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
If set to `0` (the default) sessions are not re-checked automatically, only when a new window or tab is opened or when `getSession()` is called.
|
||||
|
||||
If set to any other value, specifies how many seconds the window or tab should poll the server to update the session data.
|
||||
|
||||
When a session is checked this way (or using `getSession()`) it is active and extends the life of the current session.
|
||||
|
||||
It can be useful to use this option to prevent sessions from timing out if your application has a short session expiry time.
|
||||
|
||||
This option usually has cost implications as checking session status triggers a call to a server side route and/or a database.
|
||||
|
||||
:::note
|
||||
In NextAuth.js session state is automatically synchronized across all open windows and tabs in the same browser. If you have session expiry times of 30 days or more (the default) you probably don't need to use this option, or can set it to a high value (e.g. every 24 hours).
|
||||
:::
|
||||
@@ -7,11 +7,11 @@ NextAuth.js automatically creates simple, unbranded authentication pages for han
|
||||
|
||||
The options displayed on the sign up page are automatically generated based on the providers specified in the options passed to NextAuth.js.
|
||||
|
||||
## Using custom pages
|
||||
### Example
|
||||
|
||||
To add a custom login page, for example. You can us the `pages` option:
|
||||
|
||||
```javascript title="/pages/api/auth/[...nextauth].js"
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
...
|
||||
pages: {
|
||||
signin: '/auth/signin',
|
||||
@@ -29,7 +29,7 @@ To add a custom login page, for example. You can us the `pages` option:
|
||||
|
||||
In order to get the available authentication providers and the URLs to use for them, you can make a request to the API endpoint `/api/auth/providers`:
|
||||
|
||||
```jsx title="/pages/auth/signin"
|
||||
```jsx title="pages/auth/signin"
|
||||
import React from 'react'
|
||||
import { providers, signin } from 'next-auth/client'
|
||||
|
||||
@@ -70,7 +70,7 @@ This is easier of if you use the build in `signin()` function, as it sets the CS
|
||||
To create a sign in page that works on clients with and without client side JavaScript, you can use both the **signin()** method and the **csrfToken()** method
|
||||
:::
|
||||
|
||||
```jsx title="/pages/auth/email-signin"
|
||||
```jsx title="pages/auth/email-signin"
|
||||
import React from 'react'
|
||||
import { csrfToken, signin } from 'next-auth/client'
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ NextAuth.js is designed to work with any OAuth service, it supports OAuth 1.0, 1
|
||||
|
||||
* [Apple](/providers/apple)
|
||||
* [Auth0](/providers/auth0)
|
||||
* [Battle.net](/providers/battlenet)
|
||||
* [Box](/providers/box)
|
||||
* [Amazon Cognito](/providers/cognito)
|
||||
* [Discord](/providers/discord)
|
||||
* [Facebook](/providers/facebook)
|
||||
* [GitHub](/providers/github)
|
||||
|
||||
@@ -8,7 +8,22 @@ The NextAuth.js client library makes it easy to interact with sessions from Reac
|
||||
Some of the methods can be called both client side and server side.
|
||||
|
||||
:::note
|
||||
When using any of the client API methods server side, [context](https://nextjs.org/docs/api-reference/data-fetching/getInitialProps#context-object) must be passed as an argument. The documentation for **getSession()** has an example.
|
||||
To use client methods server side in `getServerSideProp()` or `getInitialProps()` you should add the NextAuth.js `<Provider>` in `pages/apps.js`
|
||||
|
||||
```jsx title="pages/_app.js"
|
||||
import { Provider } from 'next-auth/client'
|
||||
|
||||
export default ({ Component, pageProps }) => {
|
||||
const { session } = pageProps
|
||||
return (
|
||||
<Provider options={{ site: process.env.SITE }} session={session} >
|
||||
<Component {...pageProps} />
|
||||
</Provider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Specify the same site name as used in the route. [Documentation for `<Provider>`](/getting-started/client#provider)
|
||||
:::
|
||||
|
||||
## useSession()
|
||||
@@ -64,9 +79,9 @@ You can call `getSession()` inside a function to check if a user is signed in, o
|
||||
Note that because it exposed to the client it does not contain sensitive information such as the Session Token or OAuth service related tokens. It includes enough information (e.g name, email) to display information on a page about the user who is signed in, and an Access Token that can be used to identify the session without exposing the Session Token itself.
|
||||
:::
|
||||
|
||||
Because it is a Universal method, you can use `getSession()` in both client and server side functions, such as `getInitialProps()` in Next.js:
|
||||
Because it is a Universal method, you can use `getSession()` in both client and server side functions.
|
||||
|
||||
```jsx title="/pages/index.js"
|
||||
```jsx title="pages/index.js"
|
||||
import { getSession } from 'next-auth/client'
|
||||
|
||||
const Page = ({ session }) => (<p>
|
||||
@@ -89,36 +104,8 @@ Page.getInitialProps = async (context) => {
|
||||
export default Page
|
||||
```
|
||||
|
||||
#### Using getSession() in API routes
|
||||
|
||||
You can also get the session object in Next.js API routes:
|
||||
|
||||
```js
|
||||
import { getSession } from 'next-auth/client'
|
||||
|
||||
export default (req, res) => {
|
||||
const session = await getSession({ req })
|
||||
|
||||
if (session) {
|
||||
// Signed in
|
||||
const { accessToken } = session.user
|
||||
|
||||
// Do something with accessToken (e.g. look up user in DB)
|
||||
|
||||
res.statusCode = 200
|
||||
res.setHeader('Content-Type', 'application/json')
|
||||
res.end(JSON.stringify({ /* data */ }))
|
||||
} else {
|
||||
// Not signed in
|
||||
res.status(302).setHeader('Location', pages.newUser)
|
||||
res.end()
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
:::note
|
||||
When calling `getSession()` server side, you must pass the request object - e.g. `getSession({req})` - or you can the pass entire `context` object as it contains the `req` object.
|
||||
When calling `getSession()` server side, you must pass the request object or you can the pass entire `context` object as it contains the `req` object. e.g. `getSession(context)` or `getSession({req})`
|
||||
:::
|
||||
|
||||
---
|
||||
@@ -239,17 +226,17 @@ The URL must be considered valid by the [redirect callback handler](http://local
|
||||
|
||||
Using the supplied React `<Provider>` allows instances of `useSession()` to share the session object across components, by using [React Context](https://reactjs.org/docs/context.html) under the hood.
|
||||
|
||||
This improves performance, reduces network calls and avoids page flicker when rendering.
|
||||
This improves performance, reduces network calls and avoids page flicker when rendering. It is highly recommended and can be easily added to all pages in Next.js apps by using `pages/_app.js`.
|
||||
|
||||
It is highly recommended and can be easily added to all pages in Next.js apps by using `/pages/_app.js`.
|
||||
It is also *required* if you want to use client methods like `getSession()` in server side functions like `getServerSideProp()` or `getInitialProps()`.
|
||||
|
||||
```jsx title="/pages/_app.js"
|
||||
```jsx title="pages/_app.js"
|
||||
import { Provider } from 'next-auth/client'
|
||||
|
||||
export default ({ Component, pageProps }) => {
|
||||
const { session } = pageProps
|
||||
return (
|
||||
<Provider session={session}>
|
||||
<Provider options={{ site: process.env.SITE }} session={session} >
|
||||
<Component {...pageProps} />
|
||||
</Provider>
|
||||
)
|
||||
@@ -258,6 +245,21 @@ export default ({ Component, pageProps }) => {
|
||||
|
||||
If you pass the `session` page prop to the `<Provider>` – as in the example above – you can avoid checking the session twice on pages that support both server and client side rendering.
|
||||
|
||||
### Options
|
||||
|
||||
* `site` (required) - The URL of the site (e.g. `http://localhost:3000`)
|
||||
* `baseUrl` (optional) - The base URL for NextAuth.js (e.g. `/api/auth`)
|
||||
* `clientMaxAge` (optional) - How often to refresh the session the background (in seconds)
|
||||
|
||||
|
||||
When `clientMaxAge` is set to `0` (the default) sessions are not re-checked automatically, only when a new window or tab is opened or when `getSession()` is called. If set to any other value, specifies how many seconds the client should poll the server to check the session is valid and to keep it alive.
|
||||
|
||||
It can be useful to use this option to prevent sessions from timing out if your application has a short session expiry time. This option usually has cost implications as checking session status triggers a call to a server side route and/or a database.
|
||||
|
||||
:::tip
|
||||
In NextAuth.js session state is automatically synchronized across all open windows and tabs in the same browser. If you have session expiry times of 30 days or more (the default) you probably don't need to use the `clientMaxAge` option, or can set it to a high value (e.g. every 24 hours).
|
||||
:::
|
||||
|
||||
:::note
|
||||
See [**the Next.js documentation**](https://nextjs.org/docs/advanced-features/custom-app) for more information on **_app.js** in Next.js applications.
|
||||
:::
|
||||
|
||||
@@ -17,7 +17,7 @@ You can find a live demo of the example project at [next-auth-example.now.sh](ht
|
||||
|
||||
To add NextAuth.js to a project, first create a file called `[...nextauth].js` in `pages/api/auth`.
|
||||
|
||||
```javascript title="/pages/api/auth/[...nextauth].js"
|
||||
```javascript title="pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from 'next-auth'
|
||||
import Providers from 'next-auth/providers'
|
||||
|
||||
@@ -49,7 +49,7 @@ See the [options documentation](/configuration/options) for how to configure pro
|
||||
|
||||
The `useSession()` React Hook in the NextAuth.js client is the easiest way to check if someone is signed in.
|
||||
|
||||
```jsx title="/pages/index.js"
|
||||
```jsx title="pages/index.js"
|
||||
import React from 'react'
|
||||
import { useSession } from 'next-auth/client'
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ NextAuth.js can be used with or without a database.
|
||||
|
||||
* An open source solution that allows you to keep control of your data
|
||||
* Supports Bring Your Own Database (BYOD) and can be used with any database
|
||||
* Built-in support for for [MySQL, MariaDB, Postgres, MongoDB and SQLite](/configuration/database)
|
||||
* Built-in support for [MySQL, MariaDB, Postgres, MongoDB and SQLite](/configuration/database)
|
||||
* Works great with databases from popular hosting providers
|
||||
* Can also be used *without a database* (e.g. OAuth + JWT)
|
||||
|
||||
|
||||
@@ -3,16 +3,15 @@ id: apple
|
||||
title: Apple
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developer.apple.com/sign-in-with-apple/get-started/
|
||||
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://developer.apple.com/account/resources/identifiers/list/serviceId
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
There are two ways you can use the Sign in with Apple provider.
|
||||
|
||||
|
||||
@@ -3,15 +3,19 @@ id: auth0
|
||||
title: Auth0
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://auth0.com/docs/api/authentication#authorize-application
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://manage.auth0.com/dashboard
|
||||
|
||||
## Usage
|
||||
:::tip
|
||||
Configure your application in Auth0 as a 'Regular Web Application' (not a 'Single Page App').
|
||||
:::
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
@@ -20,8 +24,12 @@ providers: [
|
||||
Providers.Auth0({
|
||||
clientId: process.env.AUTH0_CLIENT_ID,
|
||||
clientSecret: process.env.AUTH0_CLIENT_SECRET,
|
||||
subdomain: process.env.AUTH0_SUBDOMAIN
|
||||
domain: process.env.AUTH0_DOMAIN
|
||||
})
|
||||
}
|
||||
...
|
||||
```
|
||||
```
|
||||
|
||||
:::note
|
||||
`domain` should be the fully qualified domain – e.g. `dev-s6clz2lv.eu.auth0.com`
|
||||
:::
|
||||
27
www/docs/providers/battlenet.md
Normal file
27
www/docs/providers/battlenet.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
id: battle.net
|
||||
title: Battle.net
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
https://develop.battle.net/documentation/guides/using-oauth
|
||||
|
||||
## Configuration
|
||||
|
||||
https://develop.battle.net/access/clients
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
...
|
||||
providers: [
|
||||
Providers.BattleNet({
|
||||
clientId: process.env.BATTLENET_CLIENT_ID,
|
||||
clientSecret: process.env.BATTLENET_CLIENT_SECRET,
|
||||
region: process.env.BATTLENET_REGION
|
||||
})
|
||||
}
|
||||
...
|
||||
```
|
||||
@@ -3,15 +3,15 @@ id: box
|
||||
title: Box
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developer.box.com/reference/
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://developer.box.com/guides/sso-identities-and-app-users/connect-okta-to-app-users/configure-box/
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
35
www/docs/providers/cognito.md
Normal file
35
www/docs/providers/cognito.md
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
id: cognito
|
||||
title: Amazon Cognito
|
||||
---
|
||||
|
||||
## Documentation
|
||||
|
||||
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html
|
||||
|
||||
## Configuration
|
||||
|
||||
https://console.aws.amazon.com/cognito/users/
|
||||
|
||||
You need to select your AWS region to go the the Cognito dashboard.
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
...
|
||||
providers: [
|
||||
Providers.Cognito({
|
||||
clientId: process.env.COGNITO_CLIENT_ID,
|
||||
clientSecret: process.env.COGNITO_CLIENT_SECRET,
|
||||
domain: process.env.COGNITO_DOMAIN,
|
||||
})
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
warning:::
|
||||
Make sure you select all the appropriate client settings or the OAuth flow will not work.
|
||||
:::
|
||||
|
||||

|
||||
@@ -27,7 +27,7 @@ It comes with the constraint that users authenticated in this manner are not per
|
||||
The functionality provided for credentials based authentication is intentionally limited to discourage use of passwords due to the inherent security risks associated with them and the additional complexity associated with supporting usernames and passwords.
|
||||
:::
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
The Credentials provider is specified like other providers, except that you need to define a handler for `authorize()` that accepts credentials input and returns either a `user` object or `false`.
|
||||
|
||||
@@ -35,7 +35,7 @@ If you return an object it will be persisted to the JSON Web Token and the user
|
||||
|
||||
If you return `false` or `null` then an error will be displayed advising the user to check their details.
|
||||
|
||||
```js title="/pages/api/auth/[...nextauth].js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
import Providers from `next-auth/providers`
|
||||
...
|
||||
providers: [
|
||||
@@ -65,7 +65,7 @@ providers: [
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
...
|
||||
```
|
||||
|
||||
@@ -73,7 +73,7 @@ To use your new credentials provider, you will need to create a form that posts
|
||||
|
||||
All form parameters submitted will be passed as `credentials` to your `authorize` callback.
|
||||
|
||||
```js title="/pages/signin"
|
||||
```js title="pages/signin"
|
||||
import React from 'react'
|
||||
|
||||
export default () => {
|
||||
|
||||
@@ -3,15 +3,15 @@ id: discord
|
||||
title: Discord
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://discord.com/developers/docs/topics/oauth2
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://discord.com/developers/applications
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -39,7 +39,7 @@ The Email Provider can be used with both JSON Web Tokens and database sessions,
|
||||
|
||||
Now you can add the email provider like this:
|
||||
|
||||
```js {3} title="/pages/api/auth/[...nextauth].js"
|
||||
```js {3} title="pages/api/auth/[...nextauth].js"
|
||||
providers: [
|
||||
Providers.Email({
|
||||
server: process.env.EMAIL_SERVER,
|
||||
@@ -61,7 +61,7 @@ The Email Provider can be used with both JSON Web Tokens and database sessions,
|
||||
```
|
||||
Now you can add the provider settings to the NextAuth options object in the Email Provider.
|
||||
|
||||
```js title="/pages/api/auth/[...nextauth].js"
|
||||
```js title="pages/api/auth/[...nextauth].js"
|
||||
providers: [
|
||||
Providers.Email({
|
||||
server: {
|
||||
|
||||
@@ -3,15 +3,15 @@ id: facebook
|
||||
title: Facebook
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://developers.facebook.com/apps/
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: github
|
||||
title: GitHub
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://github.com/settings/apps
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
@@ -23,7 +23,8 @@ providers: [
|
||||
})
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
:::warning
|
||||
Only allows one callback URL. May not return email address if privacy enabled.
|
||||
Only allows one callback URL per Client ID + Secret. May not return email address if privacy enabled.
|
||||
:::
|
||||
@@ -3,15 +3,15 @@ id: gitlab
|
||||
title: GitLab
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://docs.gitlab.com/ee/api/oauth2.html
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://gitlab.com/profile/applications
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
@@ -24,6 +24,7 @@ providers: [
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
:::tip
|
||||
Enable the *"read_user"* option in scope if you want to save the users email address on sign up.
|
||||
:::
|
||||
@@ -3,15 +3,15 @@ id: google
|
||||
title: Google
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developers.google.com/identity/protocols/oauth2
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://console.developers.google.com/apis/credentials
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,12 @@ id: identity-server4
|
||||
title: IdentityServer4
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://identityserver4.readthedocs.io/en/latest/
|
||||
|
||||
|
||||
## App Configuration
|
||||
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: mixer
|
||||
title: Mixer
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://dev.mixer.com/reference/oauth
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://mixer.com/lab/oauth
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,11 @@ id: okta
|
||||
title: Okta
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developer.okta.com/docs/reference/api/oidc
|
||||
|
||||
## App Configuration
|
||||
|
||||
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: slack
|
||||
title: Slack
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://api.slack.com
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://api.slack.com/apps
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: twitch
|
||||
title: Twitch
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://dev.twitch.tv/docs/authentication
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://dev.twitch.tv/console/apps
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: twitter
|
||||
title: Twitter
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://developer.twitter.com
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://developer.twitter.com/en/apps
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -3,15 +3,15 @@ id: yandex
|
||||
title: Yandex
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
## Documentation
|
||||
|
||||
https://tech.yandex.com/oauth/doc/dg/concepts/about-docpage/
|
||||
|
||||
## App Configuration
|
||||
## Configuration
|
||||
|
||||
https://oauth.yandex.com/client/new
|
||||
|
||||
## Usage
|
||||
## Example
|
||||
|
||||
```js
|
||||
import Providers from `next-auth/providers`
|
||||
|
||||
@@ -11,12 +11,15 @@ module.exports = {
|
||||
'configuration/providers',
|
||||
'configuration/database',
|
||||
'configuration/pages',
|
||||
'configuration/callbacks'
|
||||
'configuration/callbacks',
|
||||
'configuration/events'
|
||||
],
|
||||
'Authentication Providers': [
|
||||
'providers/apple',
|
||||
'providers/auth0',
|
||||
'providers/battle.net',
|
||||
'providers/box',
|
||||
'providers/cognito',
|
||||
'providers/discord',
|
||||
'providers/email',
|
||||
'providers/credentials',
|
||||
|
||||
@@ -107,6 +107,10 @@ html[data-theme='dark'] .hero {
|
||||
background: linear-gradient(0deg, rgba(222,222,222,0.075) 0%, rgba(255,255,255,0) 100%);
|
||||
}
|
||||
|
||||
.hero .container {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.hero .hero__title {
|
||||
font-size: 3rem;
|
||||
margin-bottom: 0.5rem;
|
||||
@@ -128,10 +132,6 @@ html[data-theme='dark'] .hero {
|
||||
.hero .hero__subtitle {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.hero .container {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.home-subtitle {
|
||||
|
||||
@@ -109,7 +109,7 @@ function Home () {
|
||||
<section className={`section-features ${styles.features}`}>
|
||||
<div className='container'>
|
||||
<h2 className='text--center'>
|
||||
Full stack open source authentication
|
||||
Open Source Authentication
|
||||
</h2>
|
||||
<div className='row'>
|
||||
{features.map((props, idx) => (
|
||||
@@ -150,8 +150,8 @@ function Home () {
|
||||
<p className='text--center'>
|
||||
<Link
|
||||
to='/getting-started/example'
|
||||
className='button button--secondary button--ouline button--lg rounded-pill'
|
||||
>Example Code
|
||||
className='button button--primary button--ouline button--lg rounded-pill'
|
||||
>View Example Code
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
@@ -197,7 +197,7 @@ import NextAuth from 'next-auth'
|
||||
import Providers from 'next-auth/providers'
|
||||
|
||||
const options = {
|
||||
site: 'https://example.com'
|
||||
site: 'https://example.com',
|
||||
providers: [
|
||||
// OAuth authentication providers
|
||||
Providers.Apple({
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
|
||||
.features h2 {
|
||||
font-size: 2rem;
|
||||
line-height: 3rem;
|
||||
margin: 2rem 0 4rem 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user