Compare commits
23 Commits
next-auth@
...
@auth/core
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ca87809d6 | ||
|
|
7f6967fc3c | ||
|
|
2313ef63e0 | ||
|
|
523fcbab71 | ||
|
|
83d8b447db | ||
|
|
ddffa57d00 | ||
|
|
807d5d7920 | ||
|
|
0f0dd9228a | ||
|
|
b087fdb817 | ||
|
|
443bfd6c32 | ||
|
|
7c44d916ed | ||
|
|
b489fef2e2 | ||
|
|
98add24526 | ||
|
|
0ddd47cc0a | ||
|
|
0100888d9b | ||
|
|
9eeea02fe2 | ||
|
|
0a57fea430 | ||
|
|
51750e1a06 | ||
|
|
039a14d992 | ||
|
|
da821d2789 | ||
|
|
be5c42e350 | ||
|
|
b68f461f8b | ||
|
|
95c5ba0b5d |
9
.github/sync.yml
vendored
@@ -1,5 +1,3 @@
|
||||
# Note that nextauthjs/next-auth-example syncs from the v4 branch
|
||||
|
||||
nextauthjs/sveltekit-auth-example:
|
||||
- source: apps/examples/sveltekit
|
||||
dest: .
|
||||
@@ -20,3 +18,10 @@ nextauthjs/next-auth-gatsby-example:
|
||||
deleteOrphaned: true
|
||||
- .github/FUNDING.yml
|
||||
- LICENSE
|
||||
|
||||
nextauthjs/next-auth-example:
|
||||
- source: apps/examples/nextjs
|
||||
dest: .
|
||||
deleteOrphaned: true
|
||||
- .github/FUNDING.yml
|
||||
- LICENSE
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react": "^18.0.37",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
"pg": "^8.7.3",
|
||||
|
||||
1
apps/dev/nextjs/next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"@prisma/client": "^3",
|
||||
"@supabase/supabase-js": "^2.0.5",
|
||||
"faunadb": "^4",
|
||||
"next": "13.1.1",
|
||||
"next": "13.3.0",
|
||||
"next-auth": "workspace:*",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18",
|
||||
@@ -31,7 +31,7 @@
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.29.2",
|
||||
"@types/jsonwebtoken": "^8.5.5",
|
||||
"@types/react": "^18.0.15",
|
||||
"@types/react": "18.0.37",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"dotenv": "^16.0.3",
|
||||
"fake-smtp-server": "^0.8.0",
|
||||
|
||||
@@ -102,7 +102,7 @@ export const authConfig: AuthConfig = {
|
||||
Facebook({ clientId: process.env.FACEBOOK_ID, clientSecret: process.env.FACEBOOK_SECRET }),
|
||||
Foursquare({ clientId: process.env.FOURSQUARE_ID, clientSecret: process.env.FOURSQUARE_SECRET }),
|
||||
Freshbooks({ clientId: process.env.FRESHBOOKS_ID, clientSecret: process.env.FRESHBOOKS_SECRET }),
|
||||
GitHub({ clientId: process.env.GITHUB_ID, clientSecret: process.env.GITHUB_SECRET }),
|
||||
GitHub({ clientId: process.env.GITHUB_ID, clientSecret: process.env.GITHUB_SECRET, redirectProxy: process.env.AUTH_REDIRECT_PROXY_URL }),
|
||||
Gitlab({ clientId: process.env.GITLAB_ID, clientSecret: process.env.GITLAB_SECRET }),
|
||||
Google({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET }),
|
||||
// IDS4({ clientId: process.env.IDS4_ID, clientSecret: process.env.IDS4_SECRET, issuer: process.env.IDS4_ISSUER }),
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
@@ -19,8 +23,17 @@
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
],
|
||||
"strictNullChecks": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules", "jest.config.js"]
|
||||
}
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"jest.config.js"
|
||||
]
|
||||
}
|
||||
4
apps/examples/next.config.js
Normal file
@@ -0,0 +1,4 @@
|
||||
/** @type {import("next").NextConfig} */
|
||||
module.exports = {
|
||||
reactStrictMode: true,
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
NEXTAUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32
|
||||
|
||||
APPLE_ID=
|
||||
APPLE_TEAM_ID=
|
||||
APPLE_PRIVATE_KEY=
|
||||
APPLE_KEY_ID=
|
||||
|
||||
AUTH0_ID=
|
||||
AUTH0_SECRET=
|
||||
@@ -21,8 +17,3 @@ GOOGLE_SECRET=
|
||||
|
||||
TWITTER_ID=
|
||||
TWITTER_SECRET=
|
||||
|
||||
EMAIL_SERVER=smtp://username:password@smtp.example.com:587
|
||||
EMAIL_FROM=NextAuth <noreply@example.com>
|
||||
|
||||
DATABASE_URL=sqlite://localhost/:memory:?synchronize=true
|
||||
|
||||
@@ -20,13 +20,12 @@
|
||||
"dependencies": {
|
||||
"next": "latest",
|
||||
"next-auth": "latest",
|
||||
"nodemailer": "^6",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^17",
|
||||
"@types/react": "^18.0.15",
|
||||
"typescript": "^4"
|
||||
"@types/node": "^18.16.2",
|
||||
"@types/react": "^18.2.0",
|
||||
"typescript": "^5.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,31 +4,17 @@ import FacebookProvider from "next-auth/providers/facebook"
|
||||
import GithubProvider from "next-auth/providers/github"
|
||||
import TwitterProvider from "next-auth/providers/twitter"
|
||||
import Auth0Provider from "next-auth/providers/auth0"
|
||||
// import AppleProvider from "next-auth/providers/apple"
|
||||
// import EmailProvider from "next-auth/providers/email"
|
||||
|
||||
// For more information on each option (and a full list of options) go to
|
||||
// https://next-auth.js.org/configuration/options
|
||||
export const authOptions: NextAuthOptions = {
|
||||
// https://next-auth.js.org/configuration/providers/oauth
|
||||
providers: [
|
||||
/* EmailProvider({
|
||||
server: process.env.EMAIL_SERVER,
|
||||
from: process.env.EMAIL_FROM,
|
||||
}),
|
||||
// Temporarily removing the Apple provider from the demo site as the
|
||||
// callback URL for it needs updating due to Vercel changing domains
|
||||
|
||||
Providers.Apple({
|
||||
clientId: process.env.APPLE_ID,
|
||||
clientSecret: {
|
||||
appleId: process.env.APPLE_ID,
|
||||
teamId: process.env.APPLE_TEAM_ID,
|
||||
privateKey: process.env.APPLE_PRIVATE_KEY,
|
||||
keyId: process.env.APPLE_KEY_ID,
|
||||
},
|
||||
Auth0Provider({
|
||||
clientId: process.env.AUTH0_ID,
|
||||
clientSecret: process.env.AUTH0_SECRET,
|
||||
issuer: process.env.AUTH0_ISSUER,
|
||||
}),
|
||||
*/
|
||||
FacebookProvider({
|
||||
clientId: process.env.FACEBOOK_ID,
|
||||
clientSecret: process.env.FACEBOOK_SECRET,
|
||||
@@ -44,16 +30,9 @@ export const authOptions: NextAuthOptions = {
|
||||
TwitterProvider({
|
||||
clientId: process.env.TWITTER_ID,
|
||||
clientSecret: process.env.TWITTER_SECRET,
|
||||
}),
|
||||
Auth0Provider({
|
||||
clientId: process.env.AUTH0_ID,
|
||||
clientSecret: process.env.AUTH0_SECRET,
|
||||
issuer: process.env.AUTH0_ISSUER,
|
||||
version: "2.0",
|
||||
}),
|
||||
],
|
||||
theme: {
|
||||
colorScheme: "light",
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token }) {
|
||||
token.userRole = "admin"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is an example of to protect an API route
|
||||
import { unstable_getServerSession } from "next-auth/next"
|
||||
import { getServerSession } from "next-auth/next"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
@@ -8,7 +8,7 @@ export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
|
||||
if (session) {
|
||||
return res.send({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// This is an example of how to access a session from an API route
|
||||
import { unstable_getServerSession } from "next-auth"
|
||||
import { getServerSession } from "next-auth"
|
||||
import { authOptions } from "../auth/[...nextauth]"
|
||||
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
@@ -8,6 +8,6 @@ export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
const session = await unstable_getServerSession(req, res, authOptions)
|
||||
const session = await getServerSession(req, res, authOptions)
|
||||
res.send(JSON.stringify(session, null, 2))
|
||||
}
|
||||
|
||||
@@ -13,11 +13,11 @@ export default function ServerSidePage() {
|
||||
<Layout>
|
||||
<h1>Server Side Rendering</h1>
|
||||
<p>
|
||||
This page uses the <strong>unstable_getServerSession()</strong> method
|
||||
in <strong>getServerSideProps()</strong>.
|
||||
This page uses the <strong>getServerSession()</strong> method in{" "}
|
||||
<strong>getServerSideProps()</strong>.
|
||||
</p>
|
||||
<p>
|
||||
Using <strong>unstable_getServerSession()</strong> in{" "}
|
||||
Using <strong>getServerSession()</strong> in{" "}
|
||||
<strong>getServerSideProps()</strong> is the recommended approach if you
|
||||
need to support Server Side Rendering with authentication.
|
||||
</p>
|
||||
@@ -38,11 +38,7 @@ export default function ServerSidePage() {
|
||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
return {
|
||||
props: {
|
||||
session: await getServerSession(
|
||||
context.req,
|
||||
context.res,
|
||||
authOptions
|
||||
),
|
||||
session: await getServerSession(context.req, context.res, authOptions),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,77 +18,55 @@ See below for more detailed provider settings.
|
||||
|
||||
## Vercel
|
||||
|
||||
1. Make sure to expose the Vercel [System Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) in your project settings.
|
||||
2. Create a `NEXTAUTH_SECRET` environment variable for all environments.
|
||||
1. Make sure to expose the Vercel [System Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) in your project settings. This way, we can detect the environment. (Setting `NEXTAUTH_URL` environment variable on Vercel is **unnecessary**).
|
||||
2. Create a `NEXTAUTH_SECRET` environment variable for both Production and Preview environments.
|
||||
a. You can use `openssl rand -base64 32` or https://generate-secret.vercel.app/32 to generate a random value.
|
||||
b. You **do not** need the `NEXTAUTH_URL` environment variable in Vercel.
|
||||
3. Add your provider's client ID and client secret to environment variables. _(Skip this step if not using an [OAuth Provider](/reference/providers/index))_
|
||||
4. Deploy!
|
||||
|
||||
Example repository: https://github.com/nextauthjs/next-auth-example
|
||||
|
||||
A few notes about deploying to Vercel. The environment variables are read server-side, so you do not need to prefix them with `NEXT_PUBLIC_`. When deploying here, you do not need to explicitly set the `NEXTAUTH_URL` environment variable. With other providers **you will** need to also set this environment variable.
|
||||
A few notes about deploying to Vercel. The environment variables are read server-side, so you **should not** prefix them with `NEXT_PUBLIC_` to avoid accidentally bundling a secret in the client-side JavaScript code.
|
||||
|
||||
### Securing a preview deployment
|
||||
|
||||
Securing a preview deployment (with an OAuth provider) comes with some critical obstacles. Most OAuth providers only allow a single redirect/callback URL, or at least a set of full static URLs. Meaning you cannot set the value before publishing the site and you cannot use wildcard subdomains in the callback URL settings of your OAuth provider. Here are a few ways you can still use Auth.js to secure your Preview Deployments.
|
||||
Most OAuth providers cannot be configured with multiple callback URLs or using a wildcard.
|
||||
|
||||
#### Using the Credentials Provider
|
||||
However, Auth.js **supports Preview deployments**, even **with OAuth providers**:
|
||||
|
||||
You could check in your `/pages/api/auth/[...nextauth].js` API route / configuration file to see if you're currently in a Vercel preview environment, and if so, enable a simple "credential provider", meaning username/password. Vercel offers a few built-in [system environment variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) which you could check against, like `VERCEL_ENV`. This would allow you to use this basic, for testing only, authentication strategy in your preview deployments.
|
||||
1. Determine a stable deployment URL. Eg.: A deployment whose URL does not change between builds, for example. `auth.yourdomain.com`),
|
||||
2. Set `AUTH_REDIRECT_PROXY_URL` to that URL, adding the path up until your `[...nextauth]` route. Eg.: (`https://auth.yourdomain.com/api/auth`)
|
||||
3. For your OAuth provider, set the callback URL using the stable deployment URL. Eg.: For GitHub `https://auth.yourdomain.com/api/auth/callback/github`)
|
||||
|
||||
Some things to be aware of here, include:
|
||||
:::info
|
||||
To support preview deployments, the `AUTH_SECRET` value needs to be the same for the stable deployment and deployments that will need OAuth support.
|
||||
:::
|
||||
|
||||
- Do not let this potential testing-only user have access to any critical data
|
||||
- If possible, maybe do not even connect this preview deployment to your production database
|
||||
|
||||
##### Example
|
||||
<details>
|
||||
<summary>
|
||||
<b>How does this work?</b>
|
||||
</summary>
|
||||
To support preview deployments, Auth.js uses the stable deployment URL as a redirect proxy server.
|
||||
|
||||
```js title="/pages/api/auth/[...nextauth].js"
|
||||
import NextAuth from "next-auth"
|
||||
import GoogleProvider from "next-auth/providers/google"
|
||||
import CredentialsProvider from "next-auth/providers/credentials"
|
||||
It will redirect the OAuth callback request to the preview deployment URL, but only when the `AUTH_REDIRECT_PROXY_URL` environment variable is set. The stable deployment can still act as a regular app.
|
||||
|
||||
export default NextAuth({
|
||||
providers: [
|
||||
process.env.VERCEL_ENV === "preview"
|
||||
? CredentialsProvider({
|
||||
name: "Credentials",
|
||||
credentials: {
|
||||
username: {
|
||||
label: "Username",
|
||||
type: "text",
|
||||
placeholder: "jsmith",
|
||||
},
|
||||
password: { label: "Password", type: "password" },
|
||||
},
|
||||
async authorize() {
|
||||
return {
|
||||
id: 1,
|
||||
name: "J Smith",
|
||||
email: "jsmith@example.com",
|
||||
image: "https://i.pravatar.cc/150?u=jsmith@example.com",
|
||||
}
|
||||
},
|
||||
})
|
||||
: GoogleProvider({
|
||||
clientId: process.env.GOOGLE_ID,
|
||||
clientSecret: process.env.GOOGLE_SECRET,
|
||||
}),
|
||||
],
|
||||
})
|
||||
```
|
||||
When a user initiates an OAuth sign-in flow on a preview deployment, we save its URL in the `state` query parameter but set the `redirect_uri` to the stable deployment.
|
||||
|
||||
#### Using the branch based preview URL
|
||||
Then, the OAuth provider will redirect the user to the stable deployment, which then will verify the `state` parameter and redirect the user to the preview deployment URL if the `state` is valid. This is secured by relying on the same server-side `AUTH_SECRET` for the stable deployment and the preview deployment.
|
||||
|
||||
Preview deployments at Vercel are often available via multiple URLs. For example, PR's merged to `master` or `main`, will be available the commit and PR specific preview URLs, but also the branch specific preview URLs. This branch specific URL will obviously not change as long as you work with that same branch. Therefore, you could add to your OAuth provider your `{project}-git-main-{user}.vercel.app` preview URL. As this will stay constant for that branch, you can reuse that preview deployment / URL for testing any authentication related deployments.
|
||||
See also:
|
||||
<ul>
|
||||
<li><a href="https://www.ietf.org/rfc/rfc6749.html#section-4.1.1">OAuth 2.0 specification: `state` query parameter</a></li>
|
||||
</ul>
|
||||
</details>
|
||||
|
||||
## Netlify
|
||||
|
||||
Netlify is very similar to Vercel in that you can deploy a Next.js project without almost any extra work.
|
||||
|
||||
In order to setup Auth.js correctly here, you will want to make sure you add your `NEXTAUTH_SECRET` environment variable in the project settings. If you are using the [Essential Next.js Build Plugin](https://github.com/netlify/netlify-plugin-nextjs) within your project, you **do not** need to set the `NEXTAUTH_URL` environment variable as it is set automatically as part of the build process.
|
||||
To set up Auth.js correctly here, you will want to make sure you add your `NEXTAUTH_SECRET` environment variable in the project settings. If you are using the [Essential Next.js Build Plugin](https://github.com/netlify/netlify-plugin-nextjs) within your project, you **do not** need to set the `NEXTAUTH_URL` environment variable as it is set automatically as part of the build process.
|
||||
|
||||
Netlify also exposes some [system environment variables](https://docs.netlify.com/configure-builds/environment-variables/) from which you can check which `NODE_ENV` you are currently in and much more.
|
||||
|
||||
After this, just make sure you either have your OAuth provider setup correctly with `clientId` / `clientSecret`'s and callback URLs.
|
||||
After this, make sure you either have your OAuth provider set up correctly with `clientId` / `clientSecret`'s and callback URLs.
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
Add $1 login to your page.
|
||||
|
||||
## Example
|
||||
|
||||
@example
|
||||
|
||||
```js
|
||||
import Auth from "@auth/core"
|
||||
import { $1 } from "@auth/core/providers/$2"
|
||||
import $1 from "@auth/core/providers/$2"
|
||||
|
||||
const request = new Request("https://example.com")
|
||||
const response = await AuthHandler(request, {
|
||||
providers: [$1({ clientId: "", clientSecret: "" })],
|
||||
const request = new Request(origin)
|
||||
const response = await Auth(request, {
|
||||
providers: [$1({ clientId: $3CLIENT_ID, clientSecret: $3CLIENT_SECRET })],
|
||||
})
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
@see [Link 1](https://example.com)
|
||||
- [$1 OAuth documentation](https://example.com)
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
@@ -1,29 +1,25 @@
|
||||
Add $1 login to your page.
|
||||
|
||||
## Example
|
||||
@example
|
||||
|
||||
```ts
|
||||
import { Auth } from "@auth/core"
|
||||
```js
|
||||
import Auth from "@auth/core"
|
||||
import $1 from "@auth/core/providers/$2"
|
||||
|
||||
const request = new Request("https://example.com")
|
||||
const response = await AuthHandler(request, {
|
||||
providers: [$1({ clientId: "", clientSecret: "" })],
|
||||
const request = new Request(origin)
|
||||
const response = await Auth(request, {
|
||||
providers: [$1({ clientId: $3CLIENT_ID, clientSecret: $3CLIENT_SECRET })],
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Resources
|
||||
|
||||
- [Link 1](https://example.com)
|
||||
|
||||
---
|
||||
- [$1 OAuth documentation](https://example.com)
|
||||
|
||||
## Notes
|
||||
|
||||
By default, Auth.js assumes that the $1 provider is
|
||||
based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
|
||||
:::tip
|
||||
|
||||
@@ -19,23 +19,29 @@ const icons = [
|
||||
"/img/providers/twitter.svg",
|
||||
]
|
||||
|
||||
export default React.memo(function ProviderMarquee() {
|
||||
let scale = 0.4
|
||||
|
||||
function changeScale() {
|
||||
if (typeof window !== "undefined") {
|
||||
const width = window.outerWidth
|
||||
if (width > 800) {
|
||||
scale = 0.6
|
||||
}
|
||||
|
||||
if (width > 1100) {
|
||||
scale = 0.7
|
||||
}
|
||||
|
||||
if (width > 1400) {
|
||||
scale = 0.8
|
||||
}
|
||||
if (width > 800) return 0.6
|
||||
else if (width > 1100) return 0.7
|
||||
else if (width > 1400) return 0.8
|
||||
}
|
||||
}
|
||||
|
||||
export default React.memo(function ProviderMarquee() {
|
||||
// Get initial scale on load
|
||||
const [scale, setScale] = React.useState(changeScale)
|
||||
|
||||
React.useEffect(() => {
|
||||
// Account for window size change
|
||||
function handleEvent() {
|
||||
setScale(changeScale)
|
||||
}
|
||||
|
||||
window.addEventListener("resize", handleEvent)
|
||||
return () => window.removeEventListener("resize", handleEvent)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className={styles.fullWidth}>
|
||||
|
||||
@@ -124,6 +124,9 @@ html[data-theme="dark"] hr {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.home-main .code .code-heading span {
|
||||
|
||||
12
docs/static/img/providers/42-school.svg
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1"
|
||||
id="Calque_1" sodipodi:docname="42_logo.svg" inkscape:version="0.48.2 r9819" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 -200 960 960"
|
||||
enable-background="new 0 -200 960 960" xml:space="preserve">
|
||||
<polygon id="polygon5" points="32,412.6 362.1,412.6 362.1,578 526.8,578 526.8,279.1 197.3,279.1 526.8,-51.1 362.1,-51.1
|
||||
32,279.1 "/>
|
||||
<polygon id="polygon7" points="597.9,114.2 762.7,-51.1 597.9,-51.1 "/>
|
||||
<polygon id="polygon9" points="762.7,114.2 597.9,279.1 597.9,443.9 762.7,443.9 762.7,279.1 928,114.2 928,-51.1 762.7,-51.1 "/>
|
||||
<polygon id="polygon11" points="928,279.1 762.7,443.9 928,443.9 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
docs/static/img/providers/authentik.svg
vendored
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
1
docs/static/img/providers/coinbase.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg height="447" viewBox="0 0 1101.64 196.79" width="2500" xmlns="http://www.w3.org/2000/svg"><path d="m222.34 54.94c-40.02 0-71.29 30.38-71.29 71.05s30.48 70.79 71.29 70.79 71.82-30.64 71.82-71.05c0-40.15-30.48-70.79-71.82-70.79zm.27 112.53c-22.79 0-39.49-17.7-39.49-41.47 0-24.04 16.43-41.73 39.22-41.73 23.06 0 39.75 17.96 39.75 41.73s-16.69 41.47-39.48 41.47zm80.29-81.62h19.88v108.3h31.8v-136.57h-51.68zm-231.88-1.59c16.7 0 29.95 10.3 34.98 25.62h33.66c-6.1-32.75-33.13-54.94-68.37-54.94-40.02 0-71.29 30.38-71.29 71.06s30.48 70.79 71.29 70.79c34.45 0 62.01-22.19 68.11-55.21h-33.4c-4.77 15.32-18.02 25.89-34.72 25.89-23.06 0-39.22-17.7-39.22-41.47.01-24.04 15.91-41.74 38.96-41.74zm836.1 28.53-23.32-3.43c-11.13-1.58-19.08-5.28-19.08-14 0-9.51 10.34-14.26 24.38-14.26 15.37 0 25.18 6.6 27.3 17.43h30.74c-3.45-27.47-24.65-43.58-57.24-43.58-33.66 0-55.92 17.17-55.92 41.47 0 23.24 14.58 36.72 43.99 40.94l23.32 3.43c11.4 1.58 17.76 6.08 17.76 14.53 0 10.83-11.13 15.32-26.5 15.32-18.82 0-29.42-7.66-31.01-19.28h-31.27c2.92 26.68 23.85 45.43 62.01 45.43 34.72 0 57.77-15.85 57.77-43.06 0-24.3-16.69-36.98-42.93-40.94zm-568.44-111.47c-11.66 0-20.41 8.45-20.41 20.07s8.74 20.07 20.41 20.07c11.66 0 20.41-8.45 20.41-20.07s-8.75-20.07-20.41-20.07zm466.68 103.02c0-29.58-18.02-49.39-56.18-49.39-36.04 0-56.18 18.23-60.16 46.23h31.54c1.59-10.83 10.07-19.81 28.09-19.81 16.17 0 24.12 7.13 24.12 15.85 0 11.36-14.58 14.26-32.6 16.11-24.38 2.64-54.59 11.09-54.59 42.79 0 24.57 18.29 40.41 47.44 40.41 22.79 0 37.1-9.51 44.26-24.57 1.06 13.47 11.13 22.19 25.18 22.19h18.55v-28.26h-15.64v-61.55zm-31.27 34.34c0 18.23-15.9 31.7-35.25 31.7-11.93 0-22-5.02-22-15.58 0-13.47 16.17-17.17 31.01-18.75 14.31-1.32 22.26-4.49 26.24-10.57zm-168.81-83.74c-17.76 0-32.6 7.4-43.2 19.81v-74.75h-31.8v194.15h31.27v-17.96c10.6 12.94 25.71 20.6 43.73 20.6 38.16 0 67.05-30.11 67.05-70.79s-29.42-71.06-67.05-71.06zm-4.77 112.53c-22.79 0-39.49-17.7-39.49-41.47s16.96-41.73 39.75-41.73c23.06 0 39.22 17.7 39.22 41.73 0 23.77-16.69 41.47-39.48 41.47zm-146.29-112.53c-20.67 0-34.19 8.45-42.14 20.34v-17.7h-31.54v136.56h31.8v-74.22c0-20.87 13.25-35.66 32.86-35.66 18.29 0 29.68 12.94 29.68 31.7v78.19h31.8v-80.56c.01-34.35-17.74-58.65-52.46-58.65zm647.42 66.57c0-39.09-28.62-66.56-67.05-66.56-40.81 0-70.76 30.64-70.76 71.05 0 42.53 32.07 70.79 71.29 70.79 33.13 0 59.1-19.55 65.72-47.28h-33.13c-4.77 12.15-16.43 19.02-32.07 19.02-20.41 0-35.78-12.68-39.22-34.87h105.21v-12.15zm-103.36-10.57c5.04-19.02 19.35-28.26 35.78-28.26 18.02 0 31.8 10.3 34.98 28.26z" fill="#0052ff"/></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
1
docs/static/img/providers/dropbox.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 42.4 39.5" width="2500" height="2329"><style>.st0{fill:#0062ff}</style><path class="st0" d="M10.6 1.7L0 8.5l10.6 6.7 10.6-6.7zm21.2 0L21.2 8.5l10.6 6.7 10.6-6.7zM0 22l10.6 6.8L21.2 22l-10.6-6.8zm31.8-6.8L21.2 22l10.6 6.8L42.4 22zM10.6 31l10.6 6.8L31.8 31l-10.6-6.7z"/></svg>
|
||||
|
After Width: | Height: | Size: 340 B |
24
docs/static/img/providers/duende-identity-server6.svg
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1280 1280" style="enable-background:new 0 0 1280 1280;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#252122;}
|
||||
.st1{fill:#F6971D;}
|
||||
</style>
|
||||
<path class="st0" d="M639.7,17C293.2,17,12.2,297.9,12.2,644.5S293.2,1272,639.7,1272c346.6,0,627.5-280.9,627.5-627.5
|
||||
S986.3,17,639.7,17z M639.7,1203.4c-308.7,0-558.9-250.2-558.9-558.9c0-308.7,250.2-558.9,558.9-558.9
|
||||
c308.7,0,558.9,250.2,558.9,558.9C1198.6,953.2,948.4,1203.4,639.7,1203.4z"/>
|
||||
<g>
|
||||
<path class="st1" d="M573,917.4c0.1-4,0.3-7.9,0.3-11.9c0.1-205.8,0.2-411.7,0.3-617.5c0-3.6,0-7.2,0-11.7
|
||||
c50.9-25.9,101.8-51.8,153.9-78.3c0,252.5,0,503.3,0,754.7c-37.6,22.7-75.4,45.5-113.3,68.1c-13.5,8.1-27.3,15.8-40.9,23.7
|
||||
C573.2,1002.2,573.1,959.8,573,917.4z"/>
|
||||
<path class="st0" d="M573,917.4c0.1,42.4,0.2,84.8,0.4,127.1c-34.5-4.5-67.5-14.6-99.5-27.6c-68.3-27.6-126.9-68.3-170-129
|
||||
c-75.6-106.7-69.3-237.9,15.9-337.3c59-68.8,135.1-109.6,222.2-134.6c0,43.7,0,86.3,0,129.9c-8.6,3.7-18,7.5-27.2,11.8
|
||||
c-39.9,18.6-75.4,43.1-103.4,77.7c-47.7,58.9-47.7,128.3,0.2,187.2c36.9,45.4,85.9,71.7,140.6,89.1
|
||||
C558.9,913.9,566,915.5,573,917.4z"/>
|
||||
<path class="st0" d="M923.1,448.7c7.9-15.2,15.5-29.7,23.7-45.5c37.2,58.7,73.8,116.3,111.2,175.2
|
||||
c-74.4,13.3-147.2,26.3-222.2,39.7c10.5-20.4,20-39.1,30-58.6c-33.9-16.3-69-26.5-105.8-32.6c0-41.9,0-83.3,0-124.7
|
||||
C793.4,403.3,846.4,418.4,923.1,448.7z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
3
docs/static/img/providers/eveonline.svg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="198.4" height="78.66" xml:space="preserve">
|
||||
<path d="M 0,0 0,13.88 10.97,13.88 10.97,10.31 60.69,10.31 60.69,0 0,0 z M 65.84,0 99.22,58.09 132.6,0 120.7,0 C 120.7,0 100.5,34.91 99.22,37.16 97.92,34.91 77.75,0 77.75,0 L 65.84,0 z M 137.8,0 137.8,13.88 148.7,13.88 148.7,10.31 198.4,10.31 198.4,0 137.8,0 z M 0,19.12 0,29.47 60.69,29.47 60.69,19.12 0,19.12 z M 137.8,19.12 137.8,29.47 198.4,29.47 198.4,19.12 137.8,19.12 z M 0,34.66 0,48.59 60.69,48.59 60.69,38.25 10.97,38.25 10.97,34.66 0,34.66 z M 137.8,34.66 137.8,48.59 198.4,48.59 198.4,38.25 148.7,38.25 148.7,34.66 137.8,34.66 z M 42.19,69.72 C 41.32,69.72 40.71,69.89 40.41,70.19 40.1,70.49 39.97,71.03 39.97,71.84 L 39.97,76.56 C 39.97,77.38 40.1,77.93 40.41,78.22 40.71,78.52 41.32,78.66 42.19,78.66 L 48.72,78.66 C 49.59,78.66 50.19,78.52 50.5,78.22 50.8,77.93 50.97,77.38 50.97,76.56 L 50.97,71.84 C 50.97,71.03 50.8,70.49 50.5,70.19 50.19,69.89 49.59,69.72 48.72,69.72 L 42.19,69.72 z M 64.37,69.72 64.37,78.66 66.25,78.66 66.25,73.84 C 66.25,73.66 66.23,73.43 66.22,73.19 66.2,72.94 66.18,72.69 66.16,72.41 66.26,72.53 66.38,72.67 66.5,72.78 66.62,72.89 66.75,73.01 66.91,73.16 L 73.47,78.66 74.88,78.66 74.88,69.72 73.03,69.72 73.03,74.41 C 73.03,74.52 73.05,74.7 73.06,74.91 73.07,75.11 73.09,75.47 73.12,75.97 72.99,75.81 72.82,75.66 72.66,75.5 72.49,75.35 72.31,75.18 72.09,75 L 65.81,69.72 64.37,69.72 z M 88.53,69.72 88.53,78.66 97.31,78.66 97.31,77 90.59,77 90.59,69.72 88.53,69.72 z M 109.4,69.72 109.4,78.66 111.5,78.66 111.5,69.72 109.4,69.72 z M 125.1,69.72 125.1,78.66 127,78.66 127,73.84 C 127,73.66 127,73.43 126.9,73.19 126.9,72.94 126.9,72.69 126.9,72.41 127,72.53 127.1,72.67 127.2,72.78 127.3,72.89 127.5,73.01 127.6,73.16 L 134.2,78.66 135.6,78.66 135.6,69.72 133.8,69.72 133.8,74.41 C 133.8,74.52 133.8,74.7 133.8,74.91 133.8,75.11 133.8,75.47 133.8,75.97 133.7,75.81 133.6,75.66 133.4,75.5 133.2,75.35 133,75.18 132.8,75 L 126.5,69.72 125.1,69.72 z M 149.3,69.72 149.3,78.66 158.5,78.66 158.5,77 151.3,77 151.3,74.78 155.4,74.78 155.4,73.25 151.3,73.25 151.3,71.25 158.4,71.25 158.4,69.72 149.3,69.72 z M 42.03,71.31 48.87,71.31 48.87,77 42.03,77 42.03,71.31 z" /></svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
1
docs/static/img/providers/faceit.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg height="1520" viewBox="29.3 101.1 451.7 357.9" width="2500" xmlns="http://www.w3.org/2000/svg"><path d="m481 104.8c0-1.8-1.9-3.7-1.9-3.7-1.8 0-1.8 0-3.7 1.9-37.5 58.1-76.8 116.2-114.3 176.2h-326.2c-3.7 0-5.6 5.6-1.8 7.5 134.9 50.5 331.7 127.3 440.4 170.4 3.7 1.9 7.5-1.9 7.5-3.7z" fill="#fd5a00"/><path d="m481 104.8c0-1.8-1.9-3.7-1.9-3.7-1.8 0-1.8 0-3.7 1.9-37.5 58.1-76.8 116.2-114.3 176.2l119.9 1.23z" fill="#ff690a"/></svg>
|
||||
|
After Width: | Height: | Size: 432 B |
100
docs/static/img/providers/fusionauth.svg
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 64 64.000001"
|
||||
xml:space="preserve"
|
||||
sodipodi:docname="fusionauthio-icon.svg"
|
||||
width="64"
|
||||
height="64"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
|
||||
id="metadata49"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs47" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1001"
|
||||
id="namedview45"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4.205303"
|
||||
inkscape:cx="94.166817"
|
||||
inkscape:cy="80.099998"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="Layer_1" />
|
||||
<style
|
||||
type="text/css"
|
||||
id="style2">
|
||||
.st0{fill:#EC8D53;}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<g
|
||||
id="g906"
|
||||
transform="matrix(2.6397668,0,0,2.6397668,-35.322894,-50.457841)"><g
|
||||
transform="matrix(0.15722805,0,0,0.15722805,13.258327,18.768605)"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="g6">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="path4"
|
||||
d="m 77.7,2.2 c -3.9,0 -7.5,2.1 -9.4,5.5 -2.9,5.1 -1,11.7 4.2,14.5 1.6,0.9 3.4,1.3 5.2,1.3 3.9,0 7.5,-2.1 9.4,-5.5 C 90,12.8 88.1,6.3 82.9,3.5 81.2,2.7 79.4,2.2 77.7,2.2 Z"
|
||||
class="st0" />
|
||||
</g><g
|
||||
transform="matrix(0.15722805,0,0,0.15722805,13.258327,18.768605)"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="g10">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="path8"
|
||||
d="m 16,103.6 c -3.9,0 -7.5,2.1 -9.4,5.5 -2.9,5.1 -1,11.7 4.2,14.5 1.6,0.9 3.4,1.3 5.2,1.3 3.9,0 7.5,-2.1 9.4,-5.5 2.9,-5.2 1,-11.7 -4.2,-14.5 -1.6,-0.8 -3.4,-1.3 -5.2,-1.3 z"
|
||||
class="st0" />
|
||||
</g><g
|
||||
transform="matrix(0.15722805,0,0,0.15722805,13.258327,18.768605)"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="g14">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ec8d53;fill-opacity:1"
|
||||
id="path12"
|
||||
d="m 136.4,109.1 c -3.9,0 -7.5,2.1 -9.4,5.5 -2.9,5.1 -1,11.7 4.2,14.5 1.6,0.9 3.4,1.3 5.2,1.3 3.9,0 7.5,-2.1 9.4,-5.5 2.9,-5.2 1,-11.7 -4.2,-14.5 -1.6,-0.9 -3.4,-1.3 -5.2,-1.3 z"
|
||||
class="st0" />
|
||||
</g><path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ec8d53;fill-opacity:1;stroke-width:0.15722805"
|
||||
id="path40"
|
||||
d="m 29.657213,20.891185 c -0.330179,-0.125783 -0.707527,0.04717 -0.849032,0.377347 -0.125782,0.330179 0.04717,0.707526 0.377347,0.849031 2.971611,1.132042 5.125635,3.490463 6.084726,6.304845 l -4.056484,1.084874 c -0.251565,-0.676081 -0.628912,-1.28927 -1.116319,-1.855291 -1.084873,-1.257825 -2.594263,-1.996797 -4.26088,-2.122579 -1.650895,-0.11006 -3.191729,0.440239 -4.37094,1.415052 l -2.877273,-2.845827 c 1.352161,-1.226379 3.034501,-2.091133 4.842624,-2.468481 -0.172951,-0.408793 -0.220119,-0.864754 -0.125783,-1.304992 -4.229434,0.833308 -7.814234,4.009315 -9.009167,8.301641 -0.39307,1.446498 -0.518852,2.924441 -0.361624,4.402385 0.03144,0.330179 0.314456,0.581744 0.644635,0.581744 0.03144,0 0.04717,0 0.07861,0 0.361624,-0.04717 0.613189,-0.361625 0.581743,-0.723249 -0.141505,-1.304993 -0.04717,-2.625709 0.314457,-3.899256 0.408792,-1.493666 1.147764,-2.830105 2.122578,-3.946424 l 2.892996,2.830105 c -0.754694,0.959091 -1.242101,2.138301 -1.336438,3.427571 -0.188674,2.720046 1.39933,5.141358 3.789196,6.147617 l -1.194933,3.930701 c -1.745232,-0.660357 -3.238898,-1.760954 -4.386663,-3.207452 -0.298733,0.345902 -0.67608,0.581744 -1.116319,0.691804 1.509389,1.949627 3.616245,3.396126 6.069003,4.072206 1.037705,0.283011 2.091133,0.424516 3.144561,0.424516 2.499926,0 4.93696,-0.817586 6.996648,-2.374144 0.28301,-0.220119 0.345902,-0.628912 0.125782,-0.911922 -0.220119,-0.283011 -0.628912,-0.345902 -0.911922,-0.125783 -2.499926,1.886737 -5.644487,2.547095 -8.663266,1.808123 l 1.194933,-3.946424 c 0.235842,0.04717 0.487407,0.07861 0.738972,0.09434 0.141505,0.01572 0.283011,0.01572 0.440239,0.01572 3.238898,0 5.958943,-2.531371 6.179062,-5.785992 0.03145,-0.471684 0.01572,-0.943368 -0.06289,-1.383607 l 4.056484,-1.084873 c 0.314456,1.556557 0.267287,3.191729 -0.172951,4.826901 -0.09434,0.314456 -0.188674,0.628912 -0.314456,0.943368 0.220119,0.04717 0.440238,0.125783 0.644635,0.235842 0.188673,0.11006 0.361624,0.235842 0.518852,0.39307 0.157228,-0.39307 0.298733,-0.801863 0.408793,-1.210656 1.588003,-5.817437 -1.430775,-11.807826 -7.059539,-13.96185 z m -9.213564,10.48711 c 0.172951,-2.609985 2.374143,-4.65395 4.984129,-4.65395 0.11006,0 0.235842,0 0.345902,0.01572 1.336438,0.09434 2.547094,0.691803 3.427571,1.698063 0.880477,1.006259 1.304993,2.295529 1.210656,3.631968 -0.09434,1.336438 -0.707526,2.547094 -1.713785,3.427571 -1.00626,0.880477 -2.29553,1.304993 -3.616246,1.210656 -2.751491,-0.188673 -4.826901,-2.57854 -4.638227,-5.330031 z"
|
||||
class="st1" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ec8d53;fill-opacity:1;stroke-width:0.15722805"
|
||||
id="path42"
|
||||
d="M 29.216974,28.422408 C 28.336497,27.400426 27.110118,26.787236 25.77368,26.6929 c -0.11006,-0.01572 -0.235842,-0.01572 -0.345902,-0.01572 -2.625708,0 -4.826901,2.059687 -5.015575,4.685396 -0.188673,2.767213 1.90246,5.172803 4.669673,5.361476 2.782937,0.204397 5.172803,-1.933905 5.361477,-4.669673 0.09434,-1.336438 -0.345902,-2.625708 -1.226379,-3.631968 z m -3.773473,6.383459 c -0.754695,0 -1.367884,0.06289 -1.367884,-0.345902 l 0.597466,-3.411848 c -0.345901,-0.235843 -0.566021,-0.628913 -0.566021,-1.084874 0,-0.723249 0.597467,-1.320716 1.320716,-1.320716 0.723249,0 1.320716,0.597467 1.320716,1.320716 0,0.440239 -0.22012,0.833309 -0.566021,1.084874 l 0.613189,3.380403 c 0,0.01572 0,0.01572 0,0.03144 0.01572,0.408793 -0.597466,0.345902 -1.352161,0.345902 z"
|
||||
class="st0" /></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
1
docs/static/img/providers/kakao.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="2500" height="2500" viewBox="0 0 256 256"><path fill="#FFE812" d="M256 236c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20V20C0 8.954 8.954 0 20 0h216c11.046 0 20 8.954 20 20v216z"/><path d="M128 36C70.562 36 24 72.713 24 118c0 29.279 19.466 54.97 48.748 69.477-1.593 5.494-10.237 35.344-10.581 37.689 0 0-.207 1.762.934 2.434s2.483.15 2.483.15c3.272-.457 37.943-24.811 43.944-29.04 5.995.849 12.168 1.29 18.472 1.29 57.438 0 104-36.712 104-82 0-45.287-46.562-82-104-82z"/><path fill="#FFE812" d="M70.5 146.625c-3.309 0-6-2.57-6-5.73V105.25h-9.362c-3.247 0-5.888-2.636-5.888-5.875s2.642-5.875 5.888-5.875h30.724c3.247 0 5.888 2.636 5.888 5.875s-2.642 5.875-5.888 5.875H76.5v35.645c0 3.16-2.691 5.73-6 5.73zM123.112 146.547c-2.502 0-4.416-1.016-4.993-2.65l-2.971-7.778-18.296-.001-2.973 7.783c-.575 1.631-2.488 2.646-4.99 2.646a9.155 9.155 0 0 1-3.814-.828c-1.654-.763-3.244-2.861-1.422-8.52l14.352-37.776c1.011-2.873 4.082-5.833 7.99-5.922 3.919.088 6.99 3.049 8.003 5.928l14.346 37.759c1.826 5.672.236 7.771-1.418 8.532a9.176 9.176 0 0 1-3.814.827c-.001 0 0 0 0 0zm-11.119-21.056L106 108.466l-5.993 17.025h11.986zM138 145.75c-3.171 0-5.75-2.468-5.75-5.5V99.5c0-3.309 2.748-6 6.125-6s6.125 2.691 6.125 6v35.25h12.75c3.171 0 5.75 2.468 5.75 5.5s-2.579 5.5-5.75 5.5H138zM171.334 146.547c-3.309 0-6-2.691-6-6V99.5c0-3.309 2.691-6 6-6s6 2.691 6 6v12.896l16.74-16.74c.861-.861 2.044-1.335 3.328-1.335 1.498 0 3.002.646 4.129 1.772 1.051 1.05 1.678 2.401 1.764 3.804.087 1.415-.384 2.712-1.324 3.653l-13.673 13.671 14.769 19.566a5.951 5.951 0 0 1 1.152 4.445 5.956 5.956 0 0 1-2.328 3.957 5.94 5.94 0 0 1-3.609 1.211 5.953 5.953 0 0 1-4.793-2.385l-14.071-18.644-2.082 2.082v13.091a6.01 6.01 0 0 1-6.002 6.003z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
1
docs/static/img/providers/mailru.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 115 44" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><rect id="h44px_-mail_-_bg" serif:id="h44px_@mail_&_bg" x="0" y="0" width="115" height="44" style="fill:none;"/><clipPath id="_clip1"><rect x="0" y="0" width="115" height="44"/></clipPath><g clip-path="url(#_clip1)"><path d="M115,4c0,-2.208 -1.792,-4 -4,-4l-107,0c-2.208,0 -4,1.792 -4,4l0,36c0,2.208 1.792,4 4,4l107,0c2.208,0 4,-1.792 4,-4l0,-36Z" style="fill:#005ff9;"/><g><rect x="16" y="8" width="83" height="28" style="fill:none;"/><rect x="95.68" y="10.59" width="2.654" height="18.019" style="fill:#fff;"/><path d="M92.812,28.609l-2.654,0l0,-12.769l2.654,0l0,12.769Zm-1.327,-18.467c0.989,0 1.792,0.803 1.792,1.792c0,0.989 -0.803,1.792 -1.792,1.792c-0.989,0 -1.792,-0.803 -1.792,-1.792c0,-0.989 0.803,-1.792 1.792,-1.792Z" style="fill:#fff;"/><path d="M87.29,28.609l-2.608,0l0,-1.397c-0.935,1.059 -2.582,1.725 -4.131,1.725c-3.704,0 -6.712,-3.008 -6.712,-6.713c0,-3.704 3.008,-6.712 6.712,-6.712c1.549,0 3.109,0.584 4.131,1.615l0,-1.287l2.608,0l0,12.769Zm-6.654,-10.414c2.284,0 4.081,1.634 4.081,4.029c0,2.395 -1.797,4.044 -4.081,4.044c-2.284,0 -4.02,-1.759 -4.02,-4.044c0,-2.284 1.736,-4.029 4.02,-4.029Z" style="fill:#fff;"/><path d="M54.361,28.609l-2.609,0l0,-12.769l2.609,0l0,0.892c0.579,-0.545 1.665,-1.218 3.171,-1.22c1.852,0 3.232,0.779 4.177,2.032c1.034,-1.241 2.739,-2.032 4.476,-2.032c3.26,0 5.482,2.201 5.482,5.631l0,7.466l-2.609,0l0,-7.466c0,-1.666 -1.356,-3.022 -3.022,-3.022c-1.667,0 -3.022,1.356 -3.022,3.022l0,7.466l-2.609,0l0,-7.466c0,-1.666 -1.356,-3.022 -3.022,-3.022c-1.666,0 -3.022,1.356 -3.022,3.022l0,7.466Z" style="fill:#fff;"/><path d="M34.211,22c0,2.322 -1.889,4.211 -4.211,4.211c-2.322,0 -4.211,-1.889 -4.211,-4.211c0,-2.322 1.889,-4.211 4.211,-4.211c2.322,0 4.211,1.889 4.211,4.211m-4.211,-14c-7.72,0 -14,6.28 -14,14c0,7.72 6.28,14 14,14c2.828,0 5.555,-0.842 7.886,-2.435l0.04,-0.028l-1.886,-2.192l-0.032,0.02c-1.794,1.155 -3.872,1.765 -6.008,1.765c-6.137,0 -11.13,-4.993 -11.13,-11.13c0,-6.137 4.993,-11.13 11.13,-11.13c6.137,0 11.13,4.993 11.13,11.13c0,0.795 -0.089,1.6 -0.262,2.392c-0.352,1.445 -1.364,1.887 -2.123,1.829c-0.764,-0.062 -1.658,-0.606 -1.664,-1.938l0,-1.015l0,-1.268c0,-3.905 -3.176,-7.081 -7.081,-7.081c-3.905,0 -7.081,3.176 -7.081,7.081c0,3.905 3.176,7.081 7.081,7.081c1.897,0 3.676,-0.741 5.017,-2.09c0.78,1.214 2.051,1.975 3.498,2.091c0.124,0.01 0.251,0.015 0.376,0.015c1.019,0 2.028,-0.341 2.842,-0.958c0.839,-0.638 1.466,-1.559 1.812,-2.666c0.055,-0.179 0.157,-0.588 0.157,-0.591l0.003,-0.015c0.204,-0.888 0.295,-1.773 0.295,-2.867c0,-7.72 -6.28,-14 -14,-14" style="fill:#ff9e00;fill-rule:nonzero;"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
8
docs/static/img/providers/meidum.svg
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 -55 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M72.2009141,1.42108547e-14 C112.076502,1.42108547e-14 144.399375,32.5485469 144.399375,72.6964154 C144.399375,112.844284 112.074049,145.390378 72.2009141,145.390378 C32.327779,145.390378 0,112.844284 0,72.6964154 C0,32.5485469 32.325326,1.42108547e-14 72.2009141,1.42108547e-14 Z M187.500628,4.25836743 C207.438422,4.25836743 223.601085,34.8960455 223.601085,72.6964154 L223.603538,72.6964154 C223.603538,110.486973 207.440875,141.134463 187.503081,141.134463 C167.565287,141.134463 151.402624,110.486973 151.402624,72.6964154 C151.402624,34.9058574 167.562834,4.25836743 187.500628,4.25836743 Z M243.303393,11.3867175 C250.314,11.3867175 256,38.835526 256,72.6964154 C256,106.547493 250.316453,134.006113 243.303393,134.006113 C236.290333,134.006113 230.609239,106.554852 230.609239,72.6964154 C230.609239,38.837979 236.292786,11.3867175 243.303393,11.3867175 Z" fill="#000000">
|
||||
|
||||
</path>
|
||||
</g>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
26
docs/static/img/providers/naver.svg
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="521.0783691px" height="100px" viewBox="0 0 521.0783691 100" style="enable-background:new 0 0 521.0783691 100;"
|
||||
xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#03CF5D;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M150,0l-39.2157059,100h33.3333054l4.7360992-13.2352982h37.5867004L191.1764984,100h33.3332977L185.2940979,0
|
||||
H150z M156.4685974,62.7450981L167.64711,31.5069008l11.1783905,31.2381973H156.4685974z"/>
|
||||
<polygon class="st0" points="363.2352905,62.0098 408.8234863,62.0098 408.8234863,37.9902 363.2352905,37.9902
|
||||
363.2352905,24.5098 409.3136902,24.5098 409.3136902,0 331.3724976,0 331.3724976,100 410.2940979,100 410.2940979,75.4901962
|
||||
363.2352905,75.4901962 "/>
|
||||
<polygon class="st0" points="264.2156982,65.7534027 240.6862946,0 207.35289,0 246.5685883,100 281.8627014,100 321.0783997,0
|
||||
287.7451172,0 "/>
|
||||
<polygon class="st0" points="68.1371994,53.5211983 30.8822994,0 0,0 0,100 32.3528976,100 32.3528976,46.4789009 69.6077957,100
|
||||
100.4901962,100 100.4901962,0 68.1371994,0 "/>
|
||||
<path class="st0" d="M495.7964783,65.694397l3.0326233-1.2691956
|
||||
c11.6220093-4.8646011,17.5325928-15.3901024,17.5325928-28.7482033c0-12.6320972-4.6071167-21.9770985-13.6939087-27.7756977
|
||||
C494.2207947,2.5106001,483.2662964,0,468.1940002,0h-42.213623v100h31.3724976V72.0588989h11.2745056L487.7451172,100h33.333252
|
||||
L495.7964783,65.694397z M474.0195923,46.5686989h-17.1568909V25.4902h17.1568909
|
||||
c5.8205872,0,10.5391846,4.7185993,10.5391846,10.5391998C484.5587769,41.8501015,479.8401794,46.5686989,474.0195923,46.5686989z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
1
docs/static/img/providers/netlify.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 256 105" xmlns="http://www.w3.org/2000/svg" data-theme="light" class="netlify-logo-full-small netlify-logo masthead-home-logo"><g fill="var(--_netlify-logo-lines-color)" class="netlify-logo-full-small-lines"><path d="M58.4705 103.765V77.4144L59.0166 76.8683H65.6043L66.1505 77.4144V103.765L65.6043 104.311H59.0166L58.4705 103.765Z"></path> <path d="M58.4705 26.8971V0.546133L59.0166 0H65.6043L66.1505 0.546133V26.8971L65.6043 27.4432H59.0166L58.4705 26.8971Z"></path> <path d="M35.7973 85.2395H34.8928L30.3616 80.7083V79.8037L38.8522 71.3045L43.648 71.3131L44.288 71.9445V76.7403L35.7973 85.2395Z"></path> <path d="M30.3616 24.7467V23.8336L34.8928 19.3109H35.7973L44.288 27.8016V32.5888L43.648 33.2373H38.8522L30.3616 24.7467Z"></path> <path d="M0.546133 48.3072H37.8795L38.4256 48.8533V55.4496L37.8795 55.9957H0.546133L0 55.4496V48.8533L0.546133 48.3072Z"></path> <path d="M220.314 48.3157H255.445L255.991 48.8619V55.4496L255.445 55.9957H217.566L217.02 55.4496L219.759 48.8619L220.305 48.3157H220.314Z"></path></g> <g fill="var(--_netlify-logo-text-color)" class="netlify-logo-full-small-text"><path d="M74.6666 65.8859H68.0789L67.5328 65.3397V49.92C67.5328 47.1723 66.4576 45.0475 63.1466 44.9792C61.44 44.9365 59.4944 44.9792 57.4122 45.0645L57.0965 45.3803V51.6096V65.3312L56.5504 65.8773H49.9626L49.4165 65.3312V38.9803L49.9626 38.4341H64.785C70.545 38.4341 75.2128 43.1019 75.2128 48.8619V65.3312L74.6666 65.8773V65.8859Z"></path> <path d="M106.573 54.3488L106.027 54.8949H88.9942L88.448 55.4411C88.448 56.5419 89.5488 59.8357 93.9435 59.8357C95.5904 59.8357 97.2374 59.2896 97.792 58.1888L98.3382 57.6427H104.926L105.472 58.1888C104.926 61.4827 102.178 66.432 93.935 66.432C84.5995 66.432 80.2048 59.8443 80.2048 52.1472C80.2048 44.4501 84.5995 37.8624 93.3888 37.8624C102.178 37.8624 106.573 44.4501 106.573 52.1472V54.3403V54.3488ZM98.3296 48.8533C98.3296 48.3072 97.7835 44.4587 93.3888 44.4587C88.9942 44.4587 88.448 48.3072 88.448 48.8533L88.9942 49.3995H97.7835L98.3296 48.8533Z"></path> <path d="M121.95 57.6427C121.95 58.7435 122.496 59.2896 123.597 59.2896H128.538L129.084 59.8358V65.3312L128.538 65.8774H123.597C118.656 65.8774 114.261 63.6758 114.261 57.6342V45.5509L113.715 45.0048H109.867L109.321 44.4587V38.9632L109.867 38.4171H113.715L114.261 37.8709V32.9301L114.807 32.384H121.395L121.941 32.9301V37.8709L122.487 38.4171H128.529L129.075 38.9632V44.4587L128.529 45.0048H122.487L121.941 45.5509V57.6342L121.95 57.6427Z"></path> <path d="M142.276 65.8859H135.688L135.142 65.3397V27.9808L135.688 27.4347H142.276L142.822 27.9808V65.3312L142.276 65.8773V65.8859Z"></path> <path d="M157.107 34.0224H150.519L149.973 33.4763V27.9808L150.519 27.4347H157.107L157.653 27.9808V33.4763L157.107 34.0224ZM157.107 65.8859H150.519L149.973 65.3397V38.9717L150.519 38.4256H157.107L157.653 38.9717V65.3397L157.107 65.8859Z"></path> <path d="M182.929 27.9808V33.4763L182.383 34.0224H177.442C176.341 34.0224 175.795 34.5685 175.795 35.6693V37.8709L176.341 38.4171H181.837L182.383 38.9632V44.4587L181.837 45.0048H176.341L175.795 45.5509V65.3227L175.249 65.8688H168.661L168.115 65.3227V45.5509L167.569 45.0048H163.72L163.174 44.4587V38.9632L163.72 38.4171H167.569L168.115 37.8709V35.6693C168.115 29.6277 172.51 27.4261 177.451 27.4261H182.391L182.938 27.9723L182.929 27.9808Z"></path> <path d="M203.247 66.432C201.045 71.9275 198.852 75.2213 191.164 75.2213H188.416L187.87 74.6752V69.1797L188.416 68.6336H191.164C193.911 68.6336 194.458 68.0875 195.012 66.4405V65.8944L186.223 44.4672V38.9717L186.769 38.4256H191.71L192.256 38.9717L198.844 57.6512H199.39L205.978 38.9717L206.524 38.4256H211.465L212.011 38.9717V44.4672L203.221 66.4405L203.247 66.432Z"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
5
docs/static/img/providers/osso.svg
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="104" height="104" viewBox="0 0 104 104" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M26.8125 32.4899C26.8125 32.4899 78.8125 12.1875 78.8125 29.2398C78.8125 46.2922 27.6249 56.875 27.6249 75.4834C27.6249 94.0919 78.8125 72.2335 78.8125 72.2335" stroke="white" stroke-width="4.875" stroke-linecap="round"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.8125 11.375C38.0308 11.375 47.125 20.4692 47.125 31.6875C47.125 42.9058 38.0308 52 26.8125 52C15.5942 52 6.5 42.9058 6.5 31.6875C6.5 20.4692 15.5942 11.375 26.8125 11.375ZM27.2188 21.5312C32.6035 21.5312 36.9688 25.8965 36.9688 31.2812V32.0938C36.9688 37.4785 32.6035 41.8438 27.2188 41.8438H26.4062C21.0215 41.8438 16.6562 37.4785 16.6562 32.0938V31.2812C16.6562 25.8965 21.0215 21.5312 26.4062 21.5312H27.2188Z" fill="#FFCD83"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.8125 92.625C67.5942 92.625 58.5 83.5308 58.5 72.3125C58.5 61.0942 67.5942 52 78.8125 52C90.0308 52 99.125 61.0942 99.125 72.3125C99.125 83.5308 90.0308 92.625 78.8125 92.625ZM78.4062 82.4688C73.0215 82.4688 68.6562 78.1035 68.6562 72.7188V71.9062C68.6562 66.5215 73.0215 62.1562 78.4062 62.1562H79.2188C84.6035 62.1562 88.9688 66.5215 88.9688 71.9062V72.7188C88.9688 78.1035 84.6035 82.4688 79.2188 82.4688H78.4062Z" fill="#FFCD83"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
docs/static/img/providers/osu.svg
vendored
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
1
docs/static/img/providers/pinterest.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="64" height="64"><path d="M16.132 0a16 16 0 0 0-5.771 30.952c-.13-1.312-.262-3.148 0-4.6l1.836-8a5.771 5.771 0 0 1-.525-2.361c0-2.23 1.312-3.935 2.885-3.935s1.967 1.05 1.967 2.23-.918 3.4-1.312 5.377.787 2.885 2.36 2.885 4.984-3.016 4.984-7.344-2.754-6.558-6.69-6.558-7.082 3.54-7.082 7.082c0 1.312.525 2.885 1.18 3.672a.525.525 0 0 1 .131.393l-.393 1.836c-.13.262-.262.393-.525.262-1.967-.918-3.28-3.803-3.28-6.164 0-4.984 3.672-9.705 10.623-9.705s9.836 3.935 9.836 9.18-3.54 9.968-8.263 9.968c-1.574 0-3.148-.787-3.672-1.836l-1.05 3.803c-.393 1.443-1.312 3.148-1.967 4.197A16 16 0 1 0 16.132 0z" fill="#bd081c"/></svg>
|
||||
|
After Width: | Height: | Size: 686 B |
28
docs/static/img/providers/pipedrive.svg
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg width="940" height="250" version="1.1" viewBox="0 0 940 250" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<style type="text/css">
|
||||
.st0{clip-path:url(#SVGID_2_);fill:#203232;}
|
||||
</style>
|
||||
<g transform="matrix(1.4291 0 0 1.4291 -77.63 -55.768)">
|
||||
<defs>
|
||||
<rect id="SVGID_1_" width="755.8" height="253.2"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use width="100%" height="100%" xlink:href="#SVGID_1_"/>
|
||||
</clipPath><g fill="#203232">
|
||||
<path class="st0" d="m128.3 87.8c-11.9 0-18.8 5.4-22.1 9-0.4-3.2-2.5-7.3-10.7-7.3h-17.9v18.6h7.3c1.2 0 1.6 0.4 1.6 1.6v85.1h21.2v-31.8-2.4c3.3 3 9.6 7.2 19.5 7.2 20.7 0 35.2-16.4 35.2-40 0.1-23.9-13.7-40-34.1-40m-4.3 61.5c-11.4 0-16.6-10.9-16.6-21.1 0-16 8.7-21.7 16.9-21.7 10 0 16.8 8.6 16.8 21.5-0.1 14.8-8.7 21.3-17.1 21.3" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m191 146v-45.1c0-7.6-3.7-11.3-11.2-11.3h-19v18.6h7.3c1.2 0 1.6 0.4 1.6 1.6v44.9c0 7.7 3.6 11.3 11.2 11.3h19v-18.5h-7.3c-1.1 0.1-1.6-0.4-1.6-1.5" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m246.4 87.8c-11.9 0-18.8 5.4-22.2 9-0.4-3.2-2.5-7.3-10.7-7.3h-17.8v18.6h7.3c1.2 0 1.6 0.4 1.6 1.6v85.1h21.4v-31.8-2.4c3.3 3 9.7 7.2 19.5 7.2 20.7 0 35.2-16.4 35.2-40 0-23.9-13.8-40-34.3-40m-4.3 61.5c-11.4 0-16.6-10.9-16.6-21.1 0-16 8.7-21.7 16.9-21.7 10 0 16.8 8.6 16.8 21.5 0 14.8-8.6 21.3-17.1 21.3" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m320.6 87.8c-22.9 0-38.8 16.5-38.8 40 0 23.2 17.2 40 41 40 18.7 0 30.1-11.1 30.6-11.5l0.9-0.8-9.2-15.3-1.4 1.3c-0.1 0.1-8.5 7.8-19.6 7.8-10.6 0-18.4-6.5-20.3-16.7h50.3l0.1-1.4c0-0.2 0.5-4.7 0.5-6.9 0-21.8-13.7-36.5-34.1-36.5m-16 29c2.3-7.5 8.1-11.8 16-11.8 6.4 0 11.3 4.9 12.2 11.8z" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m431.9 146v-73.9c0-7.6-3.7-11.3-11.3-11.3h-19v18.6h7.3c1.2 0 1.6 0.4 1.6 1.6v13.4c-3.1-2.8-9.2-6.5-19.8-6.5-20.6 0-35 16.5-35 40 0 23.9 13.8 40 34.2 40 11.7 0 18.5-5.4 21.8-9.2 0.4 3.3 2.6 7.5 10.5 7.5h18.4v-18.5h-7.1c-1.2-0.1-1.6-0.6-1.6-1.7m-37.9 3.3c-10.1 0-16.6-8.4-16.6-21.5 0-12.7 6.8-21.2 16.9-21.2 11.5 0 16.6 10.6 16.6 21.1 0 16-8.7 21.6-16.9 21.6" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m487.9 88.5c-8.8 0-17 5.1-21.8 13.2v-1.7c0-6.9-3.8-10.5-11.3-10.5h-18.2v18.6h7.3c1.2 0 1.6 0.4 1.6 1.6v56.3h21.2v-30.6c0-4 0.5-7.9 1.5-11.5 3.2-10.6 11.7-14.3 18.5-14.3 2.4 0 4.2 0.3 4.2 0.3l1.8 0.3v-21.1l-1.3-0.2c0-0.1-1.8-0.4-3.5-0.4" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m522.9 146v-45.1c0-7.6-3.7-11.3-11.2-11.3h-17.2v18.6h5.5c1.2 0 1.6 0.4 1.6 1.6v44.9c0 7.7 3.6 11.3 11.2 11.3h19v-18.5h-7.3c-1.1 0.1-1.6-0.4-1.6-1.5" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m603 89.6h-11.3c-6.6 0-10.2 2.3-12.3 7.9l-13.8 38.6c-0.5 1.4-0.9 3-1.3 4.6-0.4-1.5-0.9-3.2-1.4-4.6l-13.8-38.6c-2.1-5.7-5.5-7.9-12.3-7.9h-12v18.6h3.1c1.7 0 2.2 0.6 2.6 1.6l21.4 56.3h23.9l21.4-56.3c0.4-1 0.9-1.6 2.6-1.6h3.3v-18.6z" clip-path="url(#SVGID_2_)"/>
|
||||
<path class="st0" d="m639.6 87.8c-22.9 0-38.8 16.5-38.8 40 0 23.2 17.2 40 41 40 18.7 0 30.1-11.1 30.6-11.5l0.9-0.8-9.2-15.3-1.4 1.3c-0.1 0.1-8.5 7.8-19.5 7.8-10.6 0-18.4-6.5-20.3-16.7h50.3l0.1-1.4c0-0.2 0.4-4.7 0.4-6.9 0-21.8-13.7-36.5-34.1-36.5m-16 29c2.3-7.5 8.1-11.8 16-11.8 6.4 0 11.3 4.9 12.2 11.8z" clip-path="url(#SVGID_2_)"/>
|
||||
<rect class="st0" x="170.6" y="60.7" width="18.9" height="19.9" clip-path="url(#SVGID_2_)"/>
|
||||
<rect class="st0" x="502.6" y="60.7" width="18.9" height="19.9" clip-path="url(#SVGID_2_)"/>
|
||||
<polygon class="st0" points="673.3 89.6 676.1 89.6 676.1 97.2 678.2 97.2 678.2 89.6 681 89.6 681 87.8 673.3 87.8" clip-path="url(#SVGID_2_)"/>
|
||||
<polygon class="st0" points="689.3 87.8 687.2 94.3 685 87.8 682.1 87.8 682.1 97.2 684 97.2 684 90.6 684.1 90.6 686.4 97.2 688 97.2 690.3 90.6 690.3 97.2 692.2 97.2 692.2 87.8" clip-path="url(#SVGID_2_)"/>
|
||||
</g></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
25
docs/static/img/providers/saleforce.svg
vendored
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
3
docs/static/img/providers/strava.svg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 432 91"><style type="text/css">
|
||||
.st0{fill:#FC4C02;}
|
||||
</style><path class="st0" d="M74.5 49.5c1.6 2.8 2.5 6.3 2.5 10.4v0.2c0 4.2-0.8 8-2.5 11.4 -1.7 3.4-4.1 6.2-7.1 8.6 -3.1 2.3-6.8 4.1-11.2 5.4 -4.4 1.3-9.3 1.9-14.7 1.9 -8.2 0-15.9-1.1-23-3.4 -7.1-2.3-13.2-5.7-18.3-10.2l14.4-17.1c4.4 3.4 9 5.8 13.8 7.2 4.8 1.5 9.6 2.2 14.4 2.2 2.5 0 4.2-0.3 5.3-0.9 1.1-0.6 1.6-1.5 1.6-2.5v-0.2c0-1.2-0.8-2.1-2.4-2.9 -1.6-0.8-4.5-1.6-8.8-2.4 -4.5-0.9-8.8-2-12.9-3.2 -4.1-1.2-7.7-2.8-10.8-4.7 -3.1-1.9-5.6-4.3-7.4-7.2C5.4 39 4.5 35.4 4.5 31.2V31c0-3.8 0.7-7.4 2.2-10.7 1.5-3.3 3.7-6.2 6.6-8.6 2.9-2.5 6.5-4.4 10.7-5.8 4.2-1.4 9.1-2.1 14.7-2.1 7.8 0 14.7 0.9 20.5 2.8 5.9 1.8 11.1 4.6 15.8 8.3L61.9 33c-3.8-2.8-7.9-4.8-12.1-6.1 -4.3-1.3-8.3-1.9-12-1.9 -2 0-3.5 0.3-4.4 0.9 -1 0.6-1.4 1.4-1.4 2.4v0.2c0 1.1 0.7 2 2.2 2.8 1.5 0.8 4.3 1.6 8.5 2.4 5.1 0.9 9.8 2 14 3.3 4.2 1.3 7.8 3 10.9 5C70.5 44.2 72.9 46.6 74.5 49.5zM75.5 28.1h23.7v57.8h26.9V28.1h23.7V5.3H75.5V28.1zM387.9 0.3l-43.3 85.6h25.8l17.5-34.6 17.6 34.6h25.8L387.9 0.3zM267.3 0.3l43.4 85.6h-25.8l-17.5-34.6 -17.5 34.6h-17.5 -8.3 -22.4l-15.2-23h-0.2 -5.5v23h-26.9V5.3H193c7.2 0 13.1 0.8 17.8 2.5 4.6 1.6 8.4 3.9 11.2 6.7 2.5 2.4 4.3 5.2 5.5 8.3 1.2 3.1 1.8 6.7 1.8 10.8v0.2c0 5.9-1.4 10.9-4.3 14.9 -2.8 4.1-6.7 7.3-11.6 9.7l14 20.4L267.3 0.3zM202.5 35.6c0-2.6-0.9-4.5-2.8-5.8 -1.8-1.3-4.3-1.9-7.5-1.9h-11.7v15.8h11.6c3.2 0 5.8-0.7 7.6-2.1 1.8-1.4 2.8-3.3 2.8-5.8V35.6zM345.2 5.3L327.6 40 310 5.3h-25.8l43.4 85.6 43.3-85.6H345.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
docs/static/img/providers/wordpress.svg
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 122.52 122.523" xmlns="http://www.w3.org/2000/svg"><g fill="#464342"><path d="m8.708 61.26c0 20.802 12.089 38.779 29.619 47.298l-25.069-68.686c-2.916 6.536-4.55 13.769-4.55 21.388z"/><path d="m96.74 58.608c0-6.495-2.333-10.993-4.334-14.494-2.664-4.329-5.161-7.995-5.161-12.324 0-4.831 3.664-9.328 8.825-9.328.233 0 .454.029.681.042-9.35-8.566-21.807-13.796-35.489-13.796-18.36 0-34.513 9.42-43.91 23.688 1.233.037 2.395.063 3.382.063 5.497 0 14.006-.667 14.006-.667 2.833-.167 3.167 3.994.337 4.329 0 0-2.847.335-6.015.501l19.138 56.925 11.501-34.493-8.188-22.434c-2.83-.166-5.511-.501-5.511-.501-2.832-.166-2.5-4.496.332-4.329 0 0 8.679.667 13.843.667 5.496 0 14.006-.667 14.006-.667 2.835-.167 3.168 3.994.337 4.329 0 0-2.853.335-6.015.501l18.992 56.494 5.242-17.517c2.272-7.269 4.001-12.49 4.001-16.989z"/><path d="m62.184 65.857-15.768 45.819c4.708 1.384 9.687 2.141 14.846 2.141 6.12 0 11.989-1.058 17.452-2.979-.141-.225-.269-.464-.374-.724z"/><path d="m107.376 36.046c.226 1.674.354 3.471.354 5.404 0 5.333-.996 11.328-3.996 18.824l-16.053 46.413c15.624-9.111 26.133-26.038 26.133-45.426.001-9.137-2.333-17.729-6.438-25.215z"/><path d="m61.262 0c-33.779 0-61.262 27.481-61.262 61.26 0 33.783 27.483 61.263 61.262 61.263 33.778 0 61.265-27.48 61.265-61.263-.001-33.779-27.487-61.26-61.265-61.26zm0 119.715c-32.23 0-58.453-26.223-58.453-58.455 0-32.23 26.222-58.451 58.453-58.451 32.229 0 58.45 26.221 58.45 58.451 0 32.232-26.221 58.455-58.45 58.455z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
101
docs/static/img/providers/zitadel-dark.svg
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 295 81" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g transform="matrix(1,0,0,1,0,-107)">
|
||||
<g id="zitadel-logo-dark" transform="matrix(1,0,0,1,-20.9181,18.2562)">
|
||||
<rect x="20.918" y="89.57" width="294.943" height="79.632" style="fill:none;"/>
|
||||
<g transform="matrix(2.73916,0,0,1.55095,-35271.3,23.6234)">
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12622.8,-105.843)">
|
||||
<path d="M1493.5,1056.38L1493.5,1037L1496.5,1037L1496.5,1061.62L1426.02,1020.38L1496.5,979.392L1496.5,1004L1493.5,1004L1493.5,984.608L1431.98,1020.39L1493.5,1056.38Z" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g>
|
||||
<g transform="matrix(-0.0429306,-0.282967,0.160219,-0.0758207,12884.5,137.392)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear1);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,0.0758207,-0.0429306,0.282967,12878.9,10.8747)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear2);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,-0.117289,-0.207146,12943.8,65.7)">
|
||||
<path d="M212.517,110L200.392,110L190,92L179.608,110L167.483,110L190,71L212.517,110Z" style="fill:url(#_Linear3);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.160219,-0.0758207,0.0429306,-0.282967,12917.4,132.195)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear4);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.117289,0.207146,0.117289,0.207146,12897.8,5.87512)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear5);"/>
|
||||
</g>
|
||||
<g transform="matrix(-0.0429306,-0.282967,-0.160219,0.0758207,12936.8,97.6441)">
|
||||
<path d="M139.622,117L149,142L130.244,142L139.622,117Z" style="fill:url(#_Linear6);"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12622.6,-105.767)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12624.1,-96.4295)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12625,-90.2042)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12612.8,-96.1272)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0429306,0.282967,12621.7,-111.993)">
|
||||
<circle cx="1496" cy="1004" r="7" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0375643,0.247596,12637.2,-10.9628)">
|
||||
<path d="M1499.26,757.787C1499.26,757.787 1497.37,756.489 1497,755.2C1496.71,754.182 1496.57,750.662 1496.54,750C1496.41,747.303 1499.21,745.644 1499.21,745.644L1490.01,745.835C1490.01,745.835 1493.15,745.713 1493.46,750C1493.51,750.661 1493.23,753.476 1493,755.2C1492.91,756.447 1491.2,757.668 1491.2,757.668L1499.26,757.787Z" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0375643,0.247596,12639.5,4.60032)">
|
||||
<path d="M1495,760L1495,744" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0375643,0.247596,12639.5,4.60032)">
|
||||
<path d="M1498.27,757.077C1498.27,757.077 1496.71,756.46 1496.65,754.8C1496.65,753.658 1496.64,753.281 1496.65,752.016C1496.62,751.334 1496.59,750.608 1496.65,749.949C1496.78,746.836 1498.5,746.156 1498.5,746.156L1491.46,745.931C1491.46,745.931 1493.37,746.719 1493.65,749.83C1493.71,750.489 1493.69,751.528 1493.65,752.209C1493.64,753.331 1493.64,753.413 1493.65,754.518C1493.68,756.334 1492.58,756.827 1492.58,756.827L1498.27,757.077Z" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0375643,0.247596,12627.7,-0.733956)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,0.0375643,0.247596,12627.7,-0.733956)">
|
||||
<path d="M1500.86,762.056C1500.86,762.056 1499.86,760.4 1503.09,757.456C1504.91,755.797 1507.33,754.151 1509.98,752.255C1514.82,748.79 1520.68,744.94 1526.52,741.049C1531.45,737.766 1536.38,734.479 1540.82,731.68C1544.52,729.349 1547.85,727.296 1550.54,725.8C1551.07,725.506 1551.6,725.329 1552.05,725.029C1554.73,723.257 1556.85,724.968 1556.85,724.968L1552.23,716.282C1552.23,716.282 1551.99,719.454 1550,720.997C1549.57,721.333 1549.15,721.741 1548.67,722.12C1546.2,724.053 1542.99,726.344 1539.39,728.867C1535.06,731.898 1530.13,735.166 1525.19,738.438C1519.35,742.314 1513.52,746.234 1508.49,749.329C1505.74,751.023 1503.28,752.577 1501.13,753.598C1497.99,755.086 1495.28,753.617 1495.28,753.617L1500.86,762.056Z" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,-0.0375643,-0.247596,12684.9,376.33)">
|
||||
<path d="M1496.17,759.473L1555.54,720.014" style="fill:none;"/>
|
||||
</g>
|
||||
<g transform="matrix(0.160219,-0.0758207,-0.0375643,-0.247596,12684.9,376.33)">
|
||||
<path d="M1496.1,754.362C1496.1,754.362 1497.2,755.607 1501.13,753.598C1503.25,752.509 1505.74,751.023 1508.49,749.329C1513.52,746.234 1519.35,742.314 1525.19,738.438C1530.13,735.166 1534.94,731.832 1539.27,728.802C1542.87,726.279 1549.36,722.059 1549.81,721.75C1552.75,719.73 1552.18,718.196 1552.18,718.196L1555.28,724.152C1555.28,724.152 1553.77,722.905 1551.37,724.681C1550.93,725.006 1544.52,729.349 1540.82,731.68C1536.38,734.479 1531.45,737.766 1526.52,741.049C1520.68,744.94 1514.82,748.79 1509.98,752.255C1507.33,754.151 1504.89,755.771 1503.09,757.456C1499.47,760.841 1501.26,763.283 1501.26,763.283L1496.1,754.362Z" style="fill:rgb(16,16,16);"/>
|
||||
</g>
|
||||
<g transform="matrix(0.156811,0,0,0.230771,12477,-400.567)">
|
||||
<g transform="matrix(94.7456,0,0,94.7456,2811.73,2063)">
|
||||
<path d="M0.449,-0.7L0.177,-0.7C0.185,-0.682 0.197,-0.654 0.2,-0.648C0.205,-0.639 0.216,-0.628 0.239,-0.628L0.32,-0.628C0.332,-0.628 0.336,-0.62 0.334,-0.611L0.128,-0L0.389,-0C0.412,-0 0.422,-0.01 0.427,-0.02L0.45,-0.071L0.255,-0.071C0.245,-0.071 0.239,-0.078 0.242,-0.09L0.449,-0.7Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,2882.79,2063)">
|
||||
<path d="M0.214,-0.7L0.214,-0.015C0.215,-0.01 0.218,-0 0.235,-0L0.286,-0L0.286,-0.672C0.286,-0.684 0.278,-0.7 0.257,-0.7L0.214,-0.7Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,2944.37,2063)">
|
||||
<path d="M0.441,-0.7L0.155,-0.7C0.143,-0.7 0.133,-0.69 0.133,-0.678L0.133,-0.629L0.234,-0.629L0.234,-0.015C0.234,-0.01 0.237,-0 0.254,-0L0.305,-0L0.305,-0.612C0.306,-0.621 0.313,-0.629 0.323,-0.629L0.379,-0.629C0.402,-0.629 0.413,-0.639 0.417,-0.648L0.441,-0.7Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,3010.69,2063)">
|
||||
<path d="M0.422,-0L0.343,-0L0.28,-0.482L0.217,-0L0.138,-0L0.244,-0.7L0.283,-0.7C0.313,-0.7 0.318,-0.681 0.321,-0.662L0.422,-0Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,3077.96,2063)">
|
||||
<path d="M0.186,-0.7L0.186,-0L0.325,-0C0.374,-0 0.413,-0.039 0.414,-0.088L0.414,-0.612C0.413,-0.661 0.374,-0.7 0.325,-0.7L0.186,-0.7ZM0.343,-0.108C0.343,-0.081 0.325,-0.071 0.305,-0.071L0.258,-0.071L0.258,-0.628L0.305,-0.628C0.325,-0.628 0.343,-0.618 0.343,-0.592L0.343,-0.108Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,3149.02,2063)">
|
||||
<path d="M0.291,-0.071L0.291,-0.314C0.291,-0.323 0.299,-0.331 0.308,-0.331L0.338,-0.331C0.361,-0.331 0.371,-0.341 0.376,-0.35C0.379,-0.356 0.391,-0.385 0.399,-0.403L0.291,-0.403L0.291,-0.611C0.291,-0.621 0.298,-0.628 0.308,-0.628L0.366,-0.628C0.389,-0.628 0.4,-0.639 0.404,-0.648L0.428,-0.7L0.241,-0.7C0.229,-0.7 0.22,-0.691 0.219,-0.68L0.219,-0L0.379,-0C0.402,-0 0.413,-0.01 0.418,-0.019C0.421,-0.025 0.433,-0.053 0.441,-0.071L0.291,-0.071Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
<g transform="matrix(94.7456,0,0,94.7456,3220.08,2063)">
|
||||
<path d="M0.283,-0.071L0.283,-0.678C0.283,-0.69 0.273,-0.699 0.261,-0.7L0.211,-0.7L0.211,-0L0.383,-0C0.406,-0 0.417,-0.01 0.422,-0.019C0.425,-0.025 0.437,-0.053 0.445,-0.071L0.283,-0.071Z" style="fill:rgb(16,16,16);fill-rule:nonzero;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,155.247,-155.247,-41.5984,201.516,76.8392)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(155.247,-41.5984,41.5984,155.247,110.08,195.509)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,-113.649,113.649,-113.649,258.31,215.618)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear4" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-155.247,41.5984,-41.5984,-155.247,220.914,144.546)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear5" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-113.649,113.649,113.649,113.649,206.837,124.661)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
<linearGradient id="_Linear6" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-41.5984,-155.247,-155.247,41.5984,152.054,262.8)"><stop offset="0" style="stop-color:rgb(255,143,0);stop-opacity:1"/><stop offset="1" style="stop-color:rgb(254,0,255);stop-opacity:1"/></linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
2
docs/static/img/providers/zoho.svg
vendored
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
60
docs/static/img/providers/zoom.svg
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="Zoom_2011.svg"
|
||||
id="svg835"
|
||||
version="1.1"
|
||||
height="224.72337"
|
||||
width="1000">
|
||||
<metadata
|
||||
id="metadata841">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs839" />
|
||||
<sodipodi:namedview
|
||||
inkscape:current-layer="svg835"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:cy="-314.24417"
|
||||
inkscape:cx="948.1979"
|
||||
inkscape:zoom="0.49497475"
|
||||
showgrid="false"
|
||||
id="namedview837"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
inkscape:document-rotation="0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path833"
|
||||
d="m 814.1856,67.388717 c 3.82247,6.59494 5.07303,14.0983 5.48595,22.53368 l 0.5427,11.243253 v 78.62013 l 0.55449,11.25504 c 1.10899,18.38088 14.66459,31.97188 33.18704,33.12806 l 11.19606,0.55449 V 101.16565 l 0.55449,-11.243253 c 0.46011,-8.341 1.69888,-15.98593 5.58033,-22.62806 a 44.902197,44.902197 0 0 1 77.74711,0.14157 c 3.82246,6.59494 5.01403,14.23987 5.47415,22.48649 l 0.55449,11.207863 v 78.65552 l 0.55449,11.25504 c 1.15618,18.47526 14.60561,32.06626 33.18705,33.12806 L 1000,224.72337 V 89.922397 A 89.898775,89.898775 0 0 0 910.13662,0.02362708 89.662821,89.662821 0 0 0 842.71254,30.473587 89.780798,89.780798 0 0 0 775.28845,0.01182708 c -18.66402,0 -35.9831,5.66292002 -50.32915,15.44323992 C 716.20538,5.6865371 696.62113,0.01182708 685.37788,0.01182708 V 224.72337 l 11.24325,-0.55449 c 18.80559,-1.23877 32.39659,-14.46403 33.12805,-33.12806 l 0.60168,-11.25504 v -78.62013 l 0.5545,-11.243253 c 0.47191,-8.48257 1.65168,-15.93874 5.48595,-22.58087 a 45.020174,45.020174 0 0 1 38.89714,-22.39211 44.949388,44.949388 0 0 1 38.89715,22.4393 z M 44.93759,224.18067 l 11.243246,0.5427 H 224.71155 l -0.5545,-11.20785 c -1.52191,-18.47526 -14.6056,-31.97188 -33.13985,-33.17525 l -11.24324,-0.55449 H 78.667327 L 213.4683,44.937617 212.91381,33.741567 C 212.04077,15.077537 198.40259,1.5927271 179.77396,0.56631708 l -11.24325,-0.5073 L 0,0.01182708 0.55449376,11.255077 C 2.0292112,29.553367 15.301668,43.333127 33.682546,44.394927 l 11.255044,0.55449 H 146.04422 L 11.243246,179.79758 11.79774,191.04082 c 1.108987,18.52245 14.475826,31.93648 33.13985,33.12806 z M 641.26613,32.903927 a 112.34987,112.34987 0 0 1 0,158.903753 112.43246,112.43246 0 0 1 -158.93914,0 c -43.8758,-43.8758 -43.8758,-115.027963 0,-158.903753 A 112.29089,112.29089 0 0 1 561.72577,2.7082708e-5 112.37347,112.37347 0 0 1 641.26613,32.915727 Z m -31.7949,31.8185 a 67.447677,67.447677 0 0 1 0,95.349333 67.447677,67.447677 0 0 1 -95.34934,0 67.447677,67.447677 0 0 1 0,-95.349333 67.447677,67.447677 0 0 1 95.34934,0 z M 325.91256,2.7082708e-5 A 112.29089,112.29089 0 0 1 405.31134,32.915727 c 43.88759,43.86399 43.88759,115.027953 0,158.891953 a 112.43246,112.43246 0 0 1 -158.93914,0 c -43.8758,-43.8758 -43.8758,-115.027963 0,-158.903753 A 112.29089,112.29089 0 0 1 325.77098,2.7082708e-5 Z M 373.51643,64.698837 a 67.447677,67.447677 0 0 1 0,95.361123 67.447677,67.447677 0 0 1 -95.34933,0 67.447677,67.447677 0 0 1 0,-95.349333 67.447677,67.447677 0 0 1 95.34933,0 z"
|
||||
style="fill:#2d8cff;fill-rule:evenodd;stroke-width:11.79773998" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/mongodb-adapter",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"description": "mongoDB adapter for next-auth.",
|
||||
"homepage": "https://authjs.dev",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -31,7 +31,7 @@
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"mongodb": "^5 | ^4",
|
||||
"mongodb": "^5 || ^4",
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
1
packages/adapter-neo4j/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@next-auth/neo4j-adapter",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"description": "neo4j adapter for next-auth.",
|
||||
"homepage": "https://authjs.dev",
|
||||
"repository": "https://github.com/nextauthjs/next-auth",
|
||||
@@ -33,7 +33,7 @@
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"neo4j-driver": "^4.0.0",
|
||||
"neo4j-driver": "^4.0.0 || ^5.7.0",
|
||||
"next-auth": "^4"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -41,7 +41,7 @@
|
||||
"@next-auth/tsconfig": "workspace:*",
|
||||
"@types/uuid": "^8.3.3",
|
||||
"jest": "^27.4.3",
|
||||
"neo4j-driver": "^4.4.0",
|
||||
"neo4j-driver": "^5.7.0",
|
||||
"next-auth": "workspace:*"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -50,4 +50,4 @@
|
||||
"jest": {
|
||||
"preset": "@next-auth/adapter-test/jest"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,4 @@
|
||||
|
||||
---
|
||||
|
||||
Check out the documentation at [authjs.dev](https://authjs.dev/reference/core/modules/main).
|
||||
Check out the documentation at [authjs.dev](https://authjs.dev/reference/core).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@auth/core",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.1",
|
||||
"description": "Authentication for the Web.",
|
||||
"keywords": [
|
||||
"authentication",
|
||||
@@ -88,7 +88,7 @@
|
||||
"@types/cookie": "0.5.1",
|
||||
"@types/node": "18.11.10",
|
||||
"@types/nodemailer": "6.4.6",
|
||||
"@types/react": "18.0.26",
|
||||
"@types/react": "18.0.37",
|
||||
"autoprefixer": "10.4.13",
|
||||
"postcss": "8.4.19",
|
||||
"postcss-nested": "6.0.0"
|
||||
|
||||
@@ -337,4 +337,36 @@ export interface AuthConfig {
|
||||
/** @todo */
|
||||
trustHost?: boolean
|
||||
skipCSRFCheck?: typeof skipCSRFCheck
|
||||
/**
|
||||
* When set, during an OAuth sign-in flow,
|
||||
* the `redirect_uri` of the authorization request
|
||||
* will be set based on this value.
|
||||
*
|
||||
* This is useful if your OAuth Provider only supports a single `redirect_uri`
|
||||
* or you want to use OAuth on preview URLs (like Vercel), where you don't know the final deployment URL beforehand.
|
||||
*
|
||||
* The url needs to include the full path up to where Auth.js is initialized.
|
||||
*
|
||||
* @note This will auto-enable the `state` {@link OAuth2Config.checks} on the provider.
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* "https://authjs.example.com/api/auth"
|
||||
* ```
|
||||
*
|
||||
* You can also override this individually for each provider.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* GitHub({
|
||||
* ...
|
||||
* redirectProxyUrl: "https://github.example.com/api/auth"
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* @default `AUTH_REDIRECT_PROXY_URL` environment variable
|
||||
*
|
||||
* See also: [Guide: Securing a Preview Deployment](https://authjs.dev/guides/basics/deployment#securing-a-preview-deployment)
|
||||
*/
|
||||
redirectProxyUrl?: string
|
||||
}
|
||||
|
||||
@@ -56,10 +56,26 @@ export async function init({
|
||||
providers: authOptions.providers,
|
||||
url,
|
||||
providerId,
|
||||
options: authOptions,
|
||||
})
|
||||
|
||||
const maxAge = 30 * 24 * 60 * 60 // Sessions expire after 30 days of being idle by default
|
||||
|
||||
let isOnRedirectProxy = false
|
||||
if (
|
||||
(provider?.type === "oauth" || provider?.type === "oidc") &&
|
||||
provider.redirectProxyUrl
|
||||
) {
|
||||
try {
|
||||
isOnRedirectProxy =
|
||||
new URL(provider.redirectProxyUrl).origin === url.origin
|
||||
} catch {
|
||||
throw new TypeError(
|
||||
`redirectProxyUrl must be a valid URL. Received: ${provider.redirectProxyUrl}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// User provided options are overridden by other options,
|
||||
// except for the options with special handling above
|
||||
const options: InternalOptions = {
|
||||
@@ -113,6 +129,7 @@ export async function init({
|
||||
callbacks: { ...defaultCallbacks, ...authOptions.callbacks },
|
||||
logger,
|
||||
callbackUrl: url.origin,
|
||||
isOnRedirectProxy,
|
||||
}
|
||||
|
||||
// Init cookies
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { Cookie } from "../cookie.js"
|
||||
*/
|
||||
export async function getAuthorizationUrl(
|
||||
query: RequestInternal["query"],
|
||||
options: InternalOptions<"oauth">
|
||||
options: InternalOptions<"oauth" | "oidc">
|
||||
): Promise<ResponseInternal> {
|
||||
const { logger, provider } = options
|
||||
|
||||
@@ -41,12 +41,21 @@ export async function getAuthorizationUrl(
|
||||
}
|
||||
|
||||
const authParams = url.searchParams
|
||||
|
||||
let redirect_uri: string = provider.callbackUrl
|
||||
let data: object | undefined
|
||||
if (!options.isOnRedirectProxy && provider.redirectProxyUrl) {
|
||||
redirect_uri = provider.redirectProxyUrl
|
||||
data = { origin: provider.callbackUrl }
|
||||
logger.debug("using redirect proxy", { redirect_uri, data })
|
||||
}
|
||||
|
||||
const params = Object.assign(
|
||||
{
|
||||
response_type: "code",
|
||||
// clientId can technically be undefined, should we check this in assert.ts or rely on the Authorization Server to do it?
|
||||
client_id: provider.clientId,
|
||||
redirect_uri: provider.callbackUrl,
|
||||
redirect_uri,
|
||||
// @ts-expect-error TODO:
|
||||
...provider.authorization?.params,
|
||||
},
|
||||
@@ -58,7 +67,7 @@ export async function getAuthorizationUrl(
|
||||
|
||||
const cookies: Cookie[] = []
|
||||
|
||||
const state = await checks.state.create(options)
|
||||
const state = await checks.state.create(options, data)
|
||||
if (state) {
|
||||
authParams.set("state", state.value)
|
||||
cookies.push(state.cookie)
|
||||
@@ -68,7 +77,7 @@ export async function getAuthorizationUrl(
|
||||
if (as && !as.code_challenge_methods_supported?.includes("S256")) {
|
||||
// We assume S256 PKCE support, if the server does not advertise that,
|
||||
// a random `nonce` must be used for CSRF protection.
|
||||
provider.checks = ["nonce"]
|
||||
if (provider.type === "oidc") provider.checks = ["nonce"] as any
|
||||
} else {
|
||||
const { value, cookie } = await checks.pkce.create(options)
|
||||
authParams.set("code_challenge", value)
|
||||
|
||||
@@ -24,7 +24,8 @@ import type { Cookie } from "../cookie.js"
|
||||
export async function handleOAuth(
|
||||
query: RequestInternal["query"],
|
||||
cookies: RequestInternal["cookies"],
|
||||
options: InternalOptions<"oauth">
|
||||
options: InternalOptions<"oauth" | "oidc">,
|
||||
randomState?: string
|
||||
) {
|
||||
const { logger, provider } = options
|
||||
let as: o.AuthorizationServer
|
||||
@@ -71,7 +72,12 @@ export async function handleOAuth(
|
||||
|
||||
const resCookies: Cookie[] = []
|
||||
|
||||
const state = await checks.state.use(cookies, resCookies, options)
|
||||
const state = await checks.state.use(
|
||||
cookies,
|
||||
resCookies,
|
||||
options,
|
||||
randomState
|
||||
)
|
||||
|
||||
const codeGrantParams = o.validateAuthResponse(
|
||||
as,
|
||||
@@ -91,11 +97,15 @@ export async function handleOAuth(
|
||||
|
||||
const codeVerifier = await checks.pkce.use(cookies, resCookies, options)
|
||||
|
||||
let redirect_uri = provider.callbackUrl
|
||||
if (!options.isOnRedirectProxy && provider.redirectProxyUrl) {
|
||||
redirect_uri = provider.redirectProxyUrl
|
||||
}
|
||||
let codeGrantResponse = await o.authorizationCodeGrantRequest(
|
||||
as,
|
||||
client,
|
||||
codeGrantParams,
|
||||
provider.callbackUrl,
|
||||
redirect_uri,
|
||||
codeVerifier ?? "auth" // TODO: review fallback code verifier
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as jose from "jose"
|
||||
import * as o from "oauth4webapi"
|
||||
import { InvalidCheck } from "../../errors.js"
|
||||
import { encode, decode } from "../../jwt.js"
|
||||
import { decode, encode } from "../../jwt.js"
|
||||
|
||||
import type {
|
||||
CookiesOptions,
|
||||
@@ -18,7 +19,8 @@ export async function signCookie(
|
||||
type: keyof CookiesOptions,
|
||||
value: string,
|
||||
maxAge: number,
|
||||
options: InternalOptions<"oauth">
|
||||
options: InternalOptions<"oauth" | "oidc">,
|
||||
data?: any
|
||||
): Promise<Cookie> {
|
||||
const { cookies, logger } = options
|
||||
|
||||
@@ -26,13 +28,11 @@ export async function signCookie(
|
||||
|
||||
const expires = new Date()
|
||||
expires.setTime(expires.getTime() + maxAge * 1000)
|
||||
const token: any = { value }
|
||||
if (type === "state" && data) token.data = data
|
||||
return {
|
||||
name: cookies[type].name,
|
||||
value: await encode<CheckPayload>({
|
||||
...options.jwt,
|
||||
maxAge,
|
||||
token: { value },
|
||||
}),
|
||||
value: await encode({ ...options.jwt, maxAge, token }),
|
||||
options: { ...cookies[type].options, expires },
|
||||
}
|
||||
}
|
||||
@@ -92,14 +92,45 @@ export const pkce = {
|
||||
}
|
||||
|
||||
const STATE_MAX_AGE = 60 * 15 // 15 minutes in seconds
|
||||
export function decodeState(value: string):
|
||||
| {
|
||||
/** If defined, a redirect proxy is being used to support multiple OAuth apps with a single callback URL */
|
||||
origin?: string
|
||||
/** Random value for CSRF protection */
|
||||
random: string
|
||||
}
|
||||
| undefined {
|
||||
try {
|
||||
const decoder = new TextDecoder()
|
||||
return JSON.parse(decoder.decode(jose.base64url.decode(value)))
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export const state = {
|
||||
async create(options: InternalOptions<"oauth">) {
|
||||
if (!options.provider.checks.includes("state")) return
|
||||
// TODO: support customizing the state
|
||||
const value = o.generateRandomState()
|
||||
async create(options: InternalOptions<"oauth">, data?: object) {
|
||||
const { provider } = options
|
||||
if (!provider.checks.includes("state")) {
|
||||
if (data) {
|
||||
throw new InvalidCheck(
|
||||
"State data was provided but the provider is not configured to use state."
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const encodedState = jose.base64url.encode(
|
||||
JSON.stringify({ ...data, random: o.generateRandomState() })
|
||||
)
|
||||
|
||||
const maxAge = STATE_MAX_AGE
|
||||
const cookie = await signCookie("state", value, maxAge, options)
|
||||
return { cookie, value }
|
||||
const cookie = await signCookie(
|
||||
"state",
|
||||
encodedState,
|
||||
maxAge,
|
||||
options,
|
||||
data
|
||||
)
|
||||
return { cookie, value: encodedState }
|
||||
},
|
||||
/**
|
||||
* Returns state if the provider is configured to use state,
|
||||
@@ -111,7 +142,8 @@ export const state = {
|
||||
async use(
|
||||
cookies: RequestInternal["cookies"],
|
||||
resCookies: Cookie[],
|
||||
options: InternalOptions<"oauth">
|
||||
options: InternalOptions<"oauth">,
|
||||
paramRandom?: string
|
||||
): Promise<string | undefined> {
|
||||
const { provider } = options
|
||||
if (!provider.checks.includes("state")) return
|
||||
@@ -121,10 +153,23 @@ export const state = {
|
||||
if (!state) throw new InvalidCheck("State cookie was missing.")
|
||||
|
||||
// IDEA: Let the user do something with the returned state
|
||||
const value = await decode<CheckPayload>({ ...options.jwt, token: state })
|
||||
const encodedState = await decode<CheckPayload>({
|
||||
...options.jwt,
|
||||
token: state,
|
||||
})
|
||||
|
||||
if (!value?.value)
|
||||
throw new InvalidCheck("State value could not be parsed.")
|
||||
if (!encodedState?.value)
|
||||
throw new InvalidCheck("State (cookie) value could not be parsed.")
|
||||
|
||||
const decodedState = decodeState(encodedState.value)
|
||||
|
||||
if (!decodedState)
|
||||
throw new InvalidCheck("State (encoded) value could not be parsed.")
|
||||
|
||||
if (decodedState.random !== paramRandom)
|
||||
throw new InvalidCheck(
|
||||
`Random state values did not match. Expected: ${decodedState.random}. Got: ${paramRandom}`
|
||||
)
|
||||
|
||||
// Clear the state cookie after use
|
||||
resCookies.push({
|
||||
@@ -133,13 +178,13 @@ export const state = {
|
||||
options: { ...options.cookies.state.options, maxAge: 0 },
|
||||
})
|
||||
|
||||
return value.value
|
||||
return encodedState.value
|
||||
},
|
||||
}
|
||||
|
||||
const NONCE_MAX_AGE = 60 * 15 // 15 minutes in seconds
|
||||
export const nonce = {
|
||||
async create(options: InternalOptions<"oauth">) {
|
||||
async create(options: InternalOptions<"oidc">) {
|
||||
if (!options.provider.checks.includes("nonce")) return
|
||||
const value = o.generateRandomNonce()
|
||||
const maxAge = NONCE_MAX_AGE
|
||||
@@ -156,7 +201,7 @@ export const nonce = {
|
||||
async use(
|
||||
cookies: RequestInternal["cookies"],
|
||||
resCookies: Cookie[],
|
||||
options: InternalOptions<"oauth">
|
||||
options: InternalOptions<"oidc">
|
||||
): Promise<string | undefined> {
|
||||
const { provider } = options
|
||||
|
||||
|
||||
34
packages/core/src/lib/oauth/handle-state.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { InvalidCheck } from "../../errors.js"
|
||||
import { decodeState } from "./checks.js"
|
||||
|
||||
import type { OAuthConfigInternal } from "../../providers/oauth.js"
|
||||
import type { InternalOptions, RequestInternal } from "../../types.js"
|
||||
|
||||
/**
|
||||
* When the authorization flow contains a state, we check if it's a redirect proxy
|
||||
* and if so, we return the random state and the original redirect URL.
|
||||
*/
|
||||
export function handleState(
|
||||
query: RequestInternal["query"],
|
||||
provider: OAuthConfigInternal<any>,
|
||||
isOnRedirectProxy: InternalOptions["isOnRedirectProxy"]
|
||||
) {
|
||||
let randomState: string | undefined
|
||||
let proxyRedirect: string | undefined
|
||||
|
||||
if (provider.redirectProxyUrl && !query?.state) {
|
||||
throw new InvalidCheck(
|
||||
"Missing state in query, but required for redirect proxy"
|
||||
)
|
||||
}
|
||||
|
||||
const state = decodeState(query?.state)
|
||||
randomState = state?.random
|
||||
|
||||
if (isOnRedirectProxy) {
|
||||
if (!state?.origin) return { randomState }
|
||||
proxyRedirect = `${state.origin}?${new URLSearchParams(query)}`
|
||||
}
|
||||
|
||||
return { randomState, proxyRedirect }
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { merge } from "./utils/merge.js"
|
||||
|
||||
import type { InternalProvider } from "../types.js"
|
||||
import type {
|
||||
OAuthConfig,
|
||||
OAuthConfigInternal,
|
||||
@@ -8,6 +7,7 @@ import type {
|
||||
OAuthUserConfig,
|
||||
Provider,
|
||||
} from "../providers/index.js"
|
||||
import type { AuthConfig, InternalProvider } from "../types.js"
|
||||
|
||||
/**
|
||||
* Adds `signinUrl` and `callbackUrl` to each provider
|
||||
@@ -17,11 +17,12 @@ export default function parseProviders(params: {
|
||||
providers: Provider[]
|
||||
url: URL
|
||||
providerId?: string
|
||||
options: AuthConfig
|
||||
}): {
|
||||
providers: InternalProvider[]
|
||||
provider?: InternalProvider
|
||||
} {
|
||||
const { url, providerId } = params
|
||||
const { url, providerId, options } = params
|
||||
|
||||
const providers = params.providers.map((p) => {
|
||||
const provider = typeof p === "function" ? p() : p
|
||||
@@ -34,6 +35,7 @@ export default function parseProviders(params: {
|
||||
})
|
||||
|
||||
if (provider.type === "oauth" || provider.type === "oidc") {
|
||||
merged.redirectProxyUrl ??= options.redirectProxyUrl
|
||||
return normalizeOAuth(merged)
|
||||
}
|
||||
|
||||
@@ -62,11 +64,17 @@ function normalizeOAuth(
|
||||
|
||||
const userinfo = normalizeEndpoint(c.userinfo, c.issuer)
|
||||
|
||||
const checks = c.checks ?? ["pkce"]
|
||||
if (c.redirectProxyUrl) {
|
||||
if (!checks.includes("state")) checks.push("state")
|
||||
c.redirectProxyUrl = `${c.redirectProxyUrl}/callback/${c.id}`
|
||||
}
|
||||
|
||||
return {
|
||||
...c,
|
||||
authorization,
|
||||
token,
|
||||
checks: c.checks ?? ["pkce"],
|
||||
checks,
|
||||
userinfo,
|
||||
profile: c.profile ?? defaultProfile,
|
||||
}
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { handleLogin } from "../callback-handler.js"
|
||||
import { CallbackRouteError, Verification } from "../../errors.js"
|
||||
import { handleLogin } from "../callback-handler.js"
|
||||
import { handleOAuth } from "../oauth/callback.js"
|
||||
import { handleState } from "../oauth/handle-state.js"
|
||||
import { createHash } from "../web.js"
|
||||
import { handleAuthorized } from "./shared.js"
|
||||
|
||||
import type { AdapterSession } from "../../adapters.js"
|
||||
import type {
|
||||
Account,
|
||||
InternalOptions,
|
||||
RequestInternal,
|
||||
ResponseInternal,
|
||||
InternalOptions,
|
||||
Account,
|
||||
} from "../../types.js"
|
||||
import type { Cookie, SessionStore } from "../cookie.js"
|
||||
|
||||
@@ -43,10 +44,22 @@ export async function callback(params: {
|
||||
|
||||
try {
|
||||
if (provider.type === "oauth" || provider.type === "oidc") {
|
||||
const { proxyRedirect, randomState } = handleState(
|
||||
query,
|
||||
provider,
|
||||
options.isOnRedirectProxy
|
||||
)
|
||||
|
||||
if (proxyRedirect) {
|
||||
logger.debug("proxy redirect", { proxyRedirect, randomState })
|
||||
return { redirect: proxyRedirect }
|
||||
}
|
||||
|
||||
const authorizationResult = await handleOAuth(
|
||||
query,
|
||||
params.cookies,
|
||||
options
|
||||
options,
|
||||
randomState
|
||||
)
|
||||
|
||||
if (authorizationResult.cookies.length) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import type {
|
||||
export async function signin(
|
||||
query: RequestInternal["query"],
|
||||
body: RequestInternal["body"],
|
||||
options: InternalOptions<"oauth" | "email">
|
||||
options: InternalOptions<"oauth" | "oidc" | "email">
|
||||
): Promise<ResponseInternal> {
|
||||
const { url, logger, provider } = options
|
||||
try {
|
||||
|
||||
@@ -37,7 +37,7 @@ export async function toInternalRequest(
|
||||
|
||||
const action = actions.find((a) => pathname.includes(a))
|
||||
if (!action) {
|
||||
throw new UnknownAction("Cannot detect action.")
|
||||
throw new UnknownAction(`Cannot detect action in pathname (${pathname}).`)
|
||||
}
|
||||
|
||||
if (req.method !== "GET" && req.method !== "POST") {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#fff", display: "flex", justifyContent: "space-between", color: "#000", padding: 16}}>
|
||||
* <span>Built-in <b>42School</b> integration.</span>
|
||||
* <a href="https://api.intra.42.fr//">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/42-school.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/42-school
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface UserData {
|
||||
@@ -152,6 +162,57 @@ export interface FortyTwoProfile extends UserData, Record<string, any> {
|
||||
user: any | null
|
||||
}
|
||||
|
||||
/**
|
||||
* Add 42School login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/42-school
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import 42School from "@auth/core/providers/42-school"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [42School({ clientId: 42_SCHOOL_CLIENT_ID, clientSecret: 42_SCHOOL_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [42School OAuth documentation](https://api.intra.42.fr/apidoc/guides/web_application_flow)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
*
|
||||
* :::note
|
||||
* 42 returns a field on `Account` called `created_at` which is a number. See the [docs](https://api.intra.42.fr/apidoc/guides/getting_started#make-basic-requests). Make sure to add this field to your database schema, in case if you are using an [Adapter](https://authjs.dev/reference/adapters).
|
||||
* :::
|
||||
* By default, Auth.js assumes that the 42School provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The 42School provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/42-school.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function FortyTwo<P extends FortyTwoProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Apple</b> integration.</span>
|
||||
* <a href="https://apple.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/apple-dark.svg" height="48" width="48"/>
|
||||
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||
* <span style={{fontSize: "1.35rem" }}>
|
||||
* Built-in sign in with <b>Apple</b> integration.
|
||||
* </span>
|
||||
* <a href="https://apple.com" style={{backgroundColor: "black", padding: "12px", borderRadius: "100%" }}>
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/apple-dark.svg" width="24"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/apple
|
||||
*/
|
||||
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* See more at:
|
||||
* [Retrieve the User's Information from Apple ID Servers
|
||||
](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773)
|
||||
*/
|
||||
/** The returned user profile from Apple when using the profile callback. */
|
||||
export interface AppleProfile extends Record<string, any> {
|
||||
/**
|
||||
* The issuer registered claim identifies the principal that issued the identity token.
|
||||
@@ -99,6 +96,51 @@ export interface AppleProfile extends Record<string, any> {
|
||||
auth_time: number
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/apple
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*
|
||||
* Import the provider and configure it in your **Auth.js** initialization file:
|
||||
*
|
||||
* ```ts title="pages/api/auth/[...nextauth].ts"
|
||||
* import NextAuth from "next-auth"
|
||||
* import AppleProvider from "next-auth/providers/apple"
|
||||
*
|
||||
* export default NextAuth({
|
||||
* providers: [
|
||||
* AppleProvider({
|
||||
* clientId: process.env.GITHUB_ID,
|
||||
* clientSecret: process.env.GITHUB_SECRET,
|
||||
* }),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - Sign in with Apple [Overview](https://developer.apple.com/sign-in-with-apple/get-started/)
|
||||
* - Sign in with Apple [REST API](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api)
|
||||
* - [How to retrieve](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773) the user's information from Apple ID servers
|
||||
* - [Learn more about OAuth](https://authjs.dev/concepts/oauth)
|
||||
|
||||
* ### Notes
|
||||
*
|
||||
* The Apple provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/apple.ts). To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* ## Help
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*/
|
||||
export default function Apple<P extends AppleProfile>(
|
||||
options: Omit<OAuthUserConfig<P>, "clientSecret"> & {
|
||||
/**
|
||||
|
||||
@@ -1,95 +1,107 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#24292f", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Asgardeo</b> integration.</span>
|
||||
* <a href="https://wso2.com/asgardeo/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/asgardeo-dark.svg" height="48" width="48"/>
|
||||
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||
* <span style={{fontSize: "1.35rem" }}>
|
||||
* Built-in sign in with <b>Asgardeo</b> integration.
|
||||
* </span>
|
||||
* <a href="https://wso2.com/asgardeo/" style={{backgroundColor: "#ECEFF1", padding: "12px", borderRadius: "100%" }}>
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/asgardeo-dark.svg" width="24"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/asgardeo
|
||||
*/
|
||||
|
||||
import type { OIDCConfig, OIDCUserConfig } from "./index.js"
|
||||
|
||||
export interface AsgardeoProfile {
|
||||
/** The returned user profile from Asgardeo when using the profile callback. */
|
||||
export interface AsgardeoProfile extends Record<string, any> {
|
||||
/**
|
||||
* The user Asgardeo account ID
|
||||
*/
|
||||
sub: string
|
||||
/**
|
||||
* The user name
|
||||
*/
|
||||
given_name: string
|
||||
/**
|
||||
* The user email
|
||||
*/
|
||||
email: string
|
||||
/**
|
||||
* The user profile picture
|
||||
*/
|
||||
picture: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Asgardeo login to your page.
|
||||
* ## Documentation
|
||||
*
|
||||
* https://wso2.com/asgardeo/docs/guides/authentication
|
||||
*
|
||||
*
|
||||
* ## Instructions
|
||||
*
|
||||
* - Log into https://console.asgardeo.io.
|
||||
* - Next, go to "Application" tab (More info: https://wso2.com/asgardeo/docs/guides/applications/register-oidc-web-app/).
|
||||
* - Register standard based - Open id connect, application.
|
||||
* - Add callback URL: http://localhost:3000/api/auth/callback/asgardeo and https://your-domain.com/api/auth/callback/asgardeo
|
||||
* - After registering the application, go to protocol tab.
|
||||
* - Check `code` grant type.
|
||||
* - Add Authorized redirect URLs & Allowed origins fields.
|
||||
* - Make Email, First Name, Photo URL user attributes mandatory from the console.
|
||||
*
|
||||
* Create a `.env` file in the project root add the following entries:
|
||||
*
|
||||
* These values can be collected from the application created.
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* ASGARDEO_CLIENT_ID=<Copy client ID from protocol tab here>
|
||||
* ASGARDEO_CLIENT_SECRET=<Copy client from protocol tab here>
|
||||
* ASGARDEO_ISSUER=<Copy the issuer url from the info tab here>
|
||||
* https://example.com/api/auth/callback/asgardeo
|
||||
* ```
|
||||
*
|
||||
* In `pages/api/auth/[...nextauth].js` find or add the `Asgardeo` entries:
|
||||
* #### Configuration
|
||||
*
|
||||
* ```js
|
||||
* import Asgardeo from "next-auth/providers/asgardeo";
|
||||
* ...
|
||||
* providers: [
|
||||
* Asgardeo({
|
||||
* clientId: process.env.ASGARDEO_CLIENT_ID,
|
||||
* clientSecret: process.env.ASGARDEO_CLIENT_SECRET,
|
||||
* issuer: process.env.ASGARDEO_ISSUER
|
||||
* }),
|
||||
* ],
|
||||
* Import the provider and configure it in your **Auth.js** initialization file:
|
||||
*
|
||||
* ...
|
||||
* ```ts title="pages/api/auth/[...nextauth].ts"
|
||||
* import NextAuth from "next-auth"
|
||||
* import AsgardeoProvider from "next-auth/providers/asgardeo";
|
||||
*
|
||||
* export default NextAuth({
|
||||
* providers: [
|
||||
* AsgardeoProvider({
|
||||
* clientId: process.env.ASGARDEO_CLIENT_ID,
|
||||
* clientSecret: process.env.ASGARDEO_CLIENT_SECRET,
|
||||
* issuer: process.env.ASGARDEO_ISSUER
|
||||
* }),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ## Resources
|
||||
* ### Configuring Asgardeo
|
||||
*
|
||||
* @see [Asgardeo - Authentication Guide](https://wso2.com/asgardeo/docs/guides/authentication)
|
||||
* @see [Learn more about OAuth](https://authjs.dev/concepts/oauth)
|
||||
* @see [Source code](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/asgardeo.ts)
|
||||
* Follow these steps:
|
||||
*
|
||||
* ## Notes
|
||||
* 1. Log into the [Asgardeo console](https://console.asgardeo.io)
|
||||
* 2. Next, go to "Application" tab (more info [here](https://wso2.com/asgardeo/docs/guides/applications/register-oidc-web-app/))
|
||||
* 3. Register a standard based, Open ID connect, application
|
||||
* 4. Add the **callback URLs**: `http://localhost:3000/api/auth/callback/asgardeo` (development) and `https://{YOUR_DOMAIN}.com/api/auth/callback/asgardeo` (production)
|
||||
* 5. After registering the application, go to "Protocol" tab.
|
||||
* 6. Check `code` as the grant type.
|
||||
* 7. Add "Authorized redirect URLs" & "Allowed origins fields"
|
||||
* 8. Make Email, First Name, Photo URL user attributes mandatory from the console.
|
||||
*
|
||||
* By default, Auth.js assumes that the Asgardeo provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
* Then, create a `.env` file in the project root add the following entries:
|
||||
*
|
||||
* :::tip
|
||||
* ```
|
||||
* ASGARDEO_CLIENT_ID="Copy client ID from protocol tab here"
|
||||
* ASGARDEO_CLIENT_SECRET="Copy client from protocol tab here"
|
||||
* ASGARDEO_ISSUER="Copy the issuer url from the info tab here"
|
||||
* ```
|
||||
*
|
||||
* The Asgardeo provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/asgardeo.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
* ### Resources
|
||||
*
|
||||
* - [Asgardeo - Authentication Guide](https://wso2.com/asgardeo/docs/guides/authentication)
|
||||
* - [Learn more about OAuth](https://authjs.dev/concepts/oauth)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* The Asgardeo provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/asgardeo.ts). To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::info
|
||||
* By default, Auth.js assumes that the Asgardeo provider is based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) spec
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
* ## Help
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Asgardeo(
|
||||
config: OIDCUserConfig<AsgardeoProfile>
|
||||
|
||||
@@ -1,12 +1,79 @@
|
||||
/**
|
||||
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||
* <span style={{fontSize: "1.35rem" }}>
|
||||
* Built-in sign in with <b>Atlassian</b> integration.
|
||||
* </span>
|
||||
* <a href="https://www.atlassian.com/" style={{backgroundColor: "black", padding: "12px", borderRadius: "100%" }}>
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/atlassian.svg" width="24" style={{ marginTop: "-3px"}} />
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/atlassian
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
interface AtlassianProfile extends Record<string, any> {
|
||||
/** The returned user profile from Atlassian when using the profile callback. */
|
||||
export interface AtlassianProfile extends Record<string, any> {
|
||||
/**
|
||||
* The user's atlassian account ID
|
||||
*/
|
||||
account_id: string
|
||||
/**
|
||||
* The user name
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* The user's email
|
||||
*/
|
||||
email: string
|
||||
/**
|
||||
* The user's profile picture
|
||||
*/
|
||||
picture: string
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/atlassian
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*
|
||||
* Import the provider and configure it in your **Auth.js** initialization file:
|
||||
*
|
||||
* ```ts title="pages/api/auth/[...nextauth].ts"
|
||||
* import NextAuth from "next-auth"
|
||||
* import AtlassianProvider from "next-auth/providers/atlassian"
|
||||
*
|
||||
* export default NextAuth({
|
||||
* providers: [
|
||||
* AtlassianProvider({
|
||||
* clientId: process.env.ATLASSIAN_ID,
|
||||
* clientSecret: process.env.ATLASSIAN_SECRET,
|
||||
* }),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Atlassian docs](https://developer.atlassian.com/server/jira/platform/oauth/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* The Atlassian provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/atlassian.ts). To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* ## Help
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*/
|
||||
export default function Atlassian<P extends AtlassianProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#EB5424", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Auth0</b> integration.</span>
|
||||
* <a href="https://auth0.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/auth0-dark.svg" height="48" width="48"/>
|
||||
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
|
||||
* <span style={{fontSize: "1.35rem" }}>
|
||||
* Built-in sign in with <b>Auth0</b> integration.
|
||||
* </span>
|
||||
* <a href="https://auth0.com" style={{backgroundColor: "black", padding: "12px", borderRadius: "100%" }}>
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/auth0-dark.svg" width="24"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/auth0
|
||||
*/
|
||||
|
||||
import type { OIDCConfig, OIDCUserConfig } from "./index.js"
|
||||
|
||||
/** @see [User Profile Structure](https://auth0.com/docs/manage-users/user-accounts/user-profiles/user-profile-structure) */
|
||||
export interface Auth0Profile {
|
||||
/** The returned user profile from Auth0 when using the profile callback. [Reference](https://auth0.com/docs/manage-users/user-accounts/user-profiles/user-profile-structure). */
|
||||
export interface Auth0Profile extends Record<string, any> {
|
||||
/** The user's unique identifier. */
|
||||
sub: string
|
||||
/** Custom fields that store info about a user that influences the user's access, such as support plan, security roles (if not using the Authorization Core feature set), or access control groups. To learn more, read Metadata Overview. */
|
||||
@@ -75,51 +75,47 @@ export interface Auth0Profile {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Auth0 login to your page.
|
||||
* ### Setup
|
||||
*
|
||||
* ## Example
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/auth0
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* import { Auth } from "@auth/core"
|
||||
* import Auth0 from "@auth/core/providers/auth0"
|
||||
* #### Configuration
|
||||
*
|
||||
* const request = new Request("https://example.com")
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Auth0({ clientId: "", clientSecret: "", issuer: "" })],
|
||||
* Import the provider and configure it in your **Auth.js** initialization file:
|
||||
*
|
||||
* ```ts title="pages/api/auth/[...nextauth].ts"
|
||||
* import NextAuth from "next-auth"
|
||||
* import Auth0Provider from "next-auth/providers/auth0"
|
||||
*
|
||||
* export default NextAuth({
|
||||
* providers: [
|
||||
* Auth0Provider({
|
||||
* clientId: process.env.AUTH0_ID,
|
||||
* clientSecret: process.env.AUTH0_SECRET,
|
||||
* }),
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
* ### Resources
|
||||
*
|
||||
* ## Resources
|
||||
* - [Auth0 docs](https://auth0.com/docs/authenticate)
|
||||
*
|
||||
* - [Authenticate - Auth0 docs](https://auth0.com/docs/authenticate)
|
||||
* ### Notes
|
||||
*
|
||||
* ---
|
||||
* The Auth0 provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/auth0.ts). To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* ## Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Auth0 provider is
|
||||
* based on the [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Auth0 provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/auth0.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
* ## Help
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
|
||||
export default function Auth0(
|
||||
config: OIDCUserConfig<Auth0Profile>
|
||||
): OIDCConfig<Auth0Profile> {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#fd4b2d", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Authentik</b> integration.</span>
|
||||
* <a href="https://goauthentik.io/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/authentik.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/authentik
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface AuthentikProfile extends Record<string, any> {
|
||||
@@ -21,6 +31,57 @@ export interface AuthentikProfile extends Record<string, any> {
|
||||
groups: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Authentik login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/authentik
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Authentik from "@auth/core/providers/authentik"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Authentik({ clientId: AUTHENTIK_CLIENT_ID, clientSecret: AUTHENTIK_CLIENT_SECRET, issuer: AUTHENTIK_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* :::note
|
||||
* issuer should include the slug without a trailing slash – e.g., https://my-authentik-domain.com/application/o/My_Slug
|
||||
* :::
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Authentik OAuth documentation](https://goauthentik.io/docs/providers/oauth2)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Authentik provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Authentik provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/authentik.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Authentik<P extends AuthentikProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/azure-ad-b2c
|
||||
*/
|
||||
|
||||
@@ -60,7 +59,7 @@ export interface AzureADB2CProfile {
|
||||
* - Identity Provider Access Token
|
||||
* - User's Object ID
|
||||
*
|
||||
* ## Example
|
||||
* @example
|
||||
*
|
||||
* ```ts
|
||||
* import { Auth } from "@auth/core"
|
||||
@@ -75,13 +74,13 @@ export interface AzureADB2CProfile {
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Resources
|
||||
* ### Resources
|
||||
*
|
||||
* - [Azure Active Directory B2C documentation](https://learn.microsoft.com/en-us/azure/active-directory-b2c)
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Notes
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Azure AD B2C provider is
|
||||
* based on the [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#0072c6", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Azure AD</b> integration.</span>
|
||||
* <a href="https://learn.microsoft.com/en-us/azure/active-directory">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/azure-dark.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/azure-ad
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface AzureADProfile extends Record<string, any> {
|
||||
@@ -7,6 +17,101 @@ export interface AzureADProfile extends Record<string, any> {
|
||||
picture: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add AzureAd login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/azure-ad
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import AzureAd from "@auth/core/providers/azure-ad"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [AzureAd({ clientId: AZURE_AD_CLIENT_ID, clientSecret: AZURE_AD_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [AzureAd OAuth documentation](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow/)
|
||||
* - [AzureAd OAuth apps](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app/)
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* ### To allow specific Active Directory users access:
|
||||
*
|
||||
* - In https://portal.azure.com/ search for "Azure Active Directory", and select your organization.
|
||||
* - Next, go to "App Registration" in the left menu, and create a new one.
|
||||
* - Pay close attention to "Who can use this application or access this API?"
|
||||
* - This allows you to scope access to specific types of user accounts
|
||||
* - Only your tenant, all azure tenants, or all azure tenants and public Microsoft accounts (Skype, Xbox, Outlook.com, etc.)
|
||||
* - When asked for a redirection URL, use `https://yourapplication.com/api/auth/callback/azure-ad` or for development `http://localhost:3000/api/auth/callback/azure-ad`.
|
||||
* - After your App Registration is created, under "Client Credential" create your Client secret.
|
||||
* - Now copy your:
|
||||
* - Application (client) ID
|
||||
* - Directory (tenant) ID
|
||||
* - Client secret (value)
|
||||
*
|
||||
* In `.env.local` create the following entries:
|
||||
*
|
||||
* ```
|
||||
* AZURE_AD_CLIENT_ID=<copy Application (client) ID here>
|
||||
* AZURE_AD_CLIENT_SECRET=<copy generated client secret value here>
|
||||
* AZURE_AD_TENANT_ID=<copy the tenant id here>
|
||||
* ```
|
||||
*
|
||||
* That will default the tenant to use the `common` authorization endpoint. [For more details see here](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols#endpoints).
|
||||
*
|
||||
* :::note
|
||||
* Azure AD returns the profile picture in an ArrayBuffer, instead of just a URL to the image, so our provider converts it to a base64 encoded image string and returns that instead. See: https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples. The default image size is 48x48 to avoid [running out of space](https://next-auth.js.org/faq#:~:text=What%20are%20the%20disadvantages%20of%20JSON%20Web%20Tokens%3F) in case the session is saved as a JWT.
|
||||
* :::
|
||||
*
|
||||
* In `pages/api/auth/[...nextauth].js` find or add the `AzureAD` entries:
|
||||
*
|
||||
* ```js
|
||||
* import AzureADProvider from "next-auth/providers/azure-ad";
|
||||
*
|
||||
* ...
|
||||
* providers: [
|
||||
* AzureADProvider({
|
||||
* clientId: process.env.AZURE_AD_CLIENT_ID,
|
||||
* clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
|
||||
* tenantId: process.env.AZURE_AD_TENANT_ID,
|
||||
* }),
|
||||
* ]
|
||||
* ...
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the AzureAd provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The AzureAd provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/azure-ad.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function AzureAD<P extends AzureADProfile>(
|
||||
options: OAuthUserConfig<P> & {
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Battle.net</b> integration.</span>
|
||||
* <a href="https://Battle.net/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/battlenet.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/battlenet
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface BattleNetProfile extends Record<string, any> {
|
||||
@@ -10,6 +20,62 @@ export type BattleNetIssuer =
|
||||
| "https://www.battlenet.com.cn/oauth"
|
||||
| `https://${"us" | "eu" | "kr" | "tw"}.battle.net/oauth`
|
||||
|
||||
/**
|
||||
* Add Battle.net login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/battlenet
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import BattleNet from "@auth/core/providers/battlenet"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [BattleNet({ clientId: BATTLENET_CLIENT_ID, clientSecret: BATTLENET_CLIENT_SECRET. issuer: BATTLENET_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
* issuer must be one of these values, based on the available regions:
|
||||
* ```
|
||||
* type BattleNetIssuer =
|
||||
* | "https://www.battlenet.com.cn/oauth"
|
||||
* | "https://us.battle.net/oauth"
|
||||
* | "https://eu.battle.net/oauth"
|
||||
* | "https://kr.battle.net/oauth"
|
||||
* | "https://tw.battle.net/oauth"
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [BattleNet OAuth documentation](https://develop.battle.net/documentation/guides/using-oauth)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the BattleNet provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The BattleNet provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/battlenet.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function BattleNet<P extends BattleNetProfile>(
|
||||
options: OAuthUserConfig<P> & { issuer: BattleNetIssuer }
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/beyondidentity
|
||||
*/
|
||||
|
||||
@@ -27,27 +26,27 @@ export interface BeyondIdentityProfile {
|
||||
/**
|
||||
* Add Beyond Identity login to your page.
|
||||
*
|
||||
* ## Example
|
||||
* @example
|
||||
*
|
||||
* ```ts
|
||||
* import { Auth } from "@auth/core"
|
||||
* import BeyondIdentity from "@auth/core/providers/beyondidentity"
|
||||
*
|
||||
* const request = new Request("https://example.com")
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [BeyondIdentity({ clientId: "", clientSecret: "", issuer: "" })],
|
||||
* providers: [BeyondIdentity({ clientId: BEYOND_IDENTITY_CLIENT_ID, clientSecret: BEYOND_IDENTITY_CLIENT_SECRET, issuer: BEYOND_IDENTITY_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Resources
|
||||
* ### Resources
|
||||
*
|
||||
* - [Beyond Identity Developer Docs](https://developer.beyondidentity.com/)
|
||||
*
|
||||
* ---
|
||||
*
|
||||
* ## Notes
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the BeyondIdentity provider is
|
||||
* based on the [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Box(options) {
|
||||
return {
|
||||
id: "box",
|
||||
name: "Box",
|
||||
type: "oauth",
|
||||
authorization: "https://account.box.com/api/oauth2/authorize",
|
||||
token: "https://api.box.com/oauth2/token",
|
||||
userinfo: "https://api.box.com/2.0/users/me",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.name,
|
||||
email: profile.login,
|
||||
image: profile.avatar_url,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/box.svg",
|
||||
logoDark: "/box-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#0075C9",
|
||||
bgDark: "#0075C9",
|
||||
textDark: "#fff",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
89
packages/core/src/providers/box.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Box</b> integration.</span>
|
||||
* <a href="https://box.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/box.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/box
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add Box login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/box
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Box from "@auth/core/providers/box"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Box({ clientId: BOX_CLIENT_ID, clientSecret: BOX_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Box developers documentation](https://developer.box.com/reference/)
|
||||
* - [Box OAuth documentation](https://developer.box.com/guides/sso-identities-and-app-users/connect-okta-to-app-users/configure-box/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Box provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Box provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/box.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Box(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "box",
|
||||
name: "Box",
|
||||
type: "oauth",
|
||||
authorization: "https://account.box.com/api/oauth2/authorize",
|
||||
token: "https://api.box.com/oauth2/token",
|
||||
userinfo: "https://api.box.com/2.0/users/me",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.name,
|
||||
email: profile.login,
|
||||
image: profile.avatar_url,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/box.svg",
|
||||
logoDark: "/box-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#0075C9",
|
||||
bgDark: "#0075C9",
|
||||
textDark: "#fff",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>BoxyHQ SAML</b> integration.</span>
|
||||
* <a href="https://boxyhq.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/boxyhq-saml.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/boxyhq-saml
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface BoxyHQSAMLProfile extends Record<string, any> {
|
||||
@@ -7,6 +17,82 @@ export interface BoxyHQSAMLProfile extends Record<string, any> {
|
||||
lastName?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BoxyHQ SAML login to your page.
|
||||
*
|
||||
* BoxyHQ SAML is an open source service that handles the SAML login flow as an OAuth 2.0 flow, abstracting away all the complexities of the SAML protocol.
|
||||
*
|
||||
* You can deploy BoxyHQ SAML as a separate service or embed it into your app using our NPM library. [Check out the documentation for more details](https://boxyhq.com/docs/jackson/deploy)
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/boxyhq-saml
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import BoxyHQ from "@auth/core/providers/boxyhq-saml"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [BoxyHQ({ clientId: BOXYHQ_SAML_CLIENT_ID, clientSecret: BOXYHQ_SAML_CLIENT_SECRET. issuer: BOXYHQ_SAML_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [BoxyHQ OAuth documentation](https://example.com)
|
||||
*
|
||||
* ## Configuration
|
||||
*
|
||||
* SAML login requires a configuration for every tenant of yours. One common method is to use the domain for an email address to figure out which tenant they belong to. You can also use a unique tenant ID (string) from your backend for this, typically some kind of account or organization ID.
|
||||
*
|
||||
* Check out the [documentation](https://boxyhq.com/docs/jackson/saml-flow#2-saml-config-api) for more details.
|
||||
*
|
||||
*
|
||||
* On the client side you'll need to pass additional parameters `tenant` and `product` to the `signIn` function. This will allow BoxyHQL SAML to figure out the right SAML configuration and take your user to the right SAML Identity Provider to sign them in.
|
||||
*
|
||||
* ```tsx
|
||||
* import { signIn } from "next-auth/react";
|
||||
* ...
|
||||
*
|
||||
* // Map your users's email to a tenant and product
|
||||
* const tenant = email.split("@")[1];
|
||||
* const product = 'my_awesome_product';
|
||||
* ...
|
||||
* <Button
|
||||
* onClick={async (event) => {
|
||||
* event.preventDefault();
|
||||
*
|
||||
* signIn("boxyhq-saml", {}, { tenant, product });
|
||||
* }}>
|
||||
* ...
|
||||
* ```
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the BoxyHQ provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The BoxyHQ provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/boxyhq-saml.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function SAMLJackson<P extends BoxyHQSAMLProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Bungie(options) {
|
||||
return {
|
||||
id: "bungie",
|
||||
name: "Bungie",
|
||||
type: "oauth",
|
||||
authorization: "https://www.bungie.net/en/OAuth/Authorize?reauth=true",
|
||||
token: "https://www.bungie.net/platform/app/oauth/token/",
|
||||
userinfo:
|
||||
"https://www.bungie.net/platform/User/GetBungieAccount/{membershipId}/254/",
|
||||
profile(profile) {
|
||||
const { bungieNetUser: user } = profile.Response
|
||||
|
||||
return {
|
||||
id: user.membershipId,
|
||||
name: user.displayName,
|
||||
email: null,
|
||||
image: `https://www.bungie.net${
|
||||
user.profilePicturePath.startsWith("/") ? "" : "/"
|
||||
}${user.profilePicturePath}`,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
186
packages/core/src/providers/bungie.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Bungie</b> integration.</span>
|
||||
* <a href="https://bungie.net/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/bungie.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/bungie
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add Bungie login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/bungie
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Bungie from "@auth/core/providers/bungie"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Bungie({ clientId: BUNGIE_CLIENT_ID, clientSecret: BUNGIE_CLIENT_SECRET, headers: { "X-API-Key": BUNGIE_API_KEY } })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Bungie OAuth documentation](https://github.com/Bungie-net/api/wiki/OAuth-Documentation)
|
||||
*
|
||||
* ## Configuration
|
||||
*
|
||||
* :::tip
|
||||
* Bungie require all sites to run HTTPS (including local development instances).
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
* Bungie doesn't allow you to use localhost as the website URL, instead you need to use https://127.0.0.1:3000
|
||||
* :::
|
||||
*
|
||||
* Navigate to https://www.bungie.net/en/Application and fill in the required details:
|
||||
*
|
||||
* - Application name
|
||||
* - Application Status
|
||||
* - Website
|
||||
* - OAuth Client Type
|
||||
* - Confidential
|
||||
* - Redirect URL
|
||||
* - https://localhost:3000/api/auth/callback/bungie
|
||||
* - Scope
|
||||
* - `Access items like your Bungie.net notifications, memberships, and recent Bungie.Net forum activity.`
|
||||
* - Origin Header
|
||||
*
|
||||
* The following guide may be helpful:
|
||||
*
|
||||
* - [How to setup localhost with HTTPS with a Next.js app](https://medium.com/@anMagpie/secure-your-local-development-server-with-https-next-js-81ac6b8b3d68)
|
||||
*
|
||||
* #@example server
|
||||
*
|
||||
* You will need to edit your host file and point your site at `127.0.0.1`
|
||||
*
|
||||
* [How to edit my host file?](https://phoenixnap.com/kb/how-to-edit-hosts-file-in-windows-mac-or-linux)
|
||||
*
|
||||
* On Windows (Run Powershell as administrator)
|
||||
*
|
||||
* ```ps
|
||||
* Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "127.0.0.1`tdev.example.com" -Force
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* 127.0.0.1 dev.example.com
|
||||
* ```
|
||||
*
|
||||
* ### Create certificate
|
||||
*
|
||||
* Creating a certificate for localhost is easy with openssl. Just put the following command in the terminal. The output will be two files: localhost.key and localhost.crt.
|
||||
*
|
||||
* ```bash
|
||||
* openssl req -x509 -out localhost.crt -keyout localhost.key \
|
||||
* -newkey rsa:2048 -nodes -sha256 \
|
||||
* -subj "/CN=localhost" -extensions EXT -config <( \
|
||||
* printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
|
||||
* ```
|
||||
*
|
||||
* :::tip
|
||||
* **Windows**
|
||||
*
|
||||
* The OpenSSL executable is distributed with [Git](https://git-scm.com/download/win]9) for Windows.
|
||||
* Once installed you will find the openssl.exe file in `C:/Program Files/Git/mingw64/bin` which you can add to the system PATH environment variable if it’s not already done.
|
||||
*
|
||||
* Add environment variable `OPENSSL_CONF=C:/Program Files/Git/mingw64/ssl/openssl.cnf`
|
||||
*
|
||||
* ```bash
|
||||
* req -x509 -out localhost.crt -keyout localhost.key \
|
||||
* -newkey rsa:2048 -nodes -sha256 \
|
||||
* -subj "/CN=localhost"
|
||||
* ```
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* Create directory `certificates` and place `localhost.key` and `localhost.crt`
|
||||
*
|
||||
* You can create a `server.js` in the root of your project and run it with `node server.js` to test Sign in with Bungie integration locally:
|
||||
*
|
||||
* ```js
|
||||
* const { createServer } = require("https")
|
||||
* const { parse } = require("url")
|
||||
* const next = require("next")
|
||||
* const fs = require("fs")
|
||||
*
|
||||
* const dev = process.env.NODE_ENV !== "production"
|
||||
* const app = next({ dev })
|
||||
* const handle = app.getRequestHandler()
|
||||
*
|
||||
* const httpsOptions = {
|
||||
* key: fs.readFileSync("./certificates/localhost.key"),
|
||||
* cert: fs.readFileSync("./certificates/localhost.crt"),
|
||||
* }
|
||||
*
|
||||
* app.prepare().then(() => {
|
||||
* createServer(httpsOptions, (req, res) => {
|
||||
* const parsedUrl = parse(req.url, true)
|
||||
* handle(req, res, parsedUrl)
|
||||
* }).listen(3000, (err) => {
|
||||
* if (err) throw err
|
||||
* console.log("> Ready on https://localhost:3000")
|
||||
* })
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Bungie provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Bungie provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/bungie.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Bungie(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "bungie",
|
||||
name: "Bungie",
|
||||
type: "oauth",
|
||||
authorization: "https://www.bungie.net/en/OAuth/Authorize?reauth=true",
|
||||
token: "https://www.bungie.net/platform/app/oauth/token/",
|
||||
userinfo:
|
||||
"https://www.bungie.net/platform/User/GetBungieAccount/{membershipId}/254/",
|
||||
profile(profile) {
|
||||
const { bungieNetUser: user } = profile.Response
|
||||
|
||||
return {
|
||||
id: user.membershipId,
|
||||
name: user.displayName,
|
||||
email: null,
|
||||
image: `https://www.bungie.net${
|
||||
user.profilePicturePath.startsWith("/") ? "" : "/"
|
||||
}${user.profilePicturePath}`,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Cognito</b> integration.</span>
|
||||
* <a href="https://docs.aws.amazon.com/cognito">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/cognito.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/cognito
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface CognitoProfile extends Record<string, any> {
|
||||
@@ -7,6 +17,62 @@ export interface CognitoProfile extends Record<string, any> {
|
||||
picture: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Cognito login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/cognito
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Cognito from "@auth/core/providers/cognito"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Cognito({ clientId: COGNITO_CLIENT_ID, clientSecret: COGNITO_CLIENT_SECRET, issuer: COGNITO_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Cognito OAuth documentation](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-userpools-server-contract-reference.html)
|
||||
*
|
||||
* ### Notes
|
||||
* You need to select your AWS region to go the the Cognito dashboard.
|
||||
*
|
||||
* :::tip
|
||||
* The issuer is a URL, that looks like this: https://cognito-idp.{region}.amazonaws.com/{PoolId}
|
||||
* :::
|
||||
* `PoolId` is from General Settings in Cognito, not to be confused with the App Client ID.
|
||||
* :::warning
|
||||
* Make sure you select all the appropriate client settings or the OAuth flow will not work.
|
||||
* :::
|
||||
*
|
||||
* By default, Auth.js assumes that the Cognito provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Cognito provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/cognito.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Cognito<P extends CognitoProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Coinbase(options) {
|
||||
return {
|
||||
id: "coinbase",
|
||||
name: "Coinbase",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://www.coinbase.com/oauth/authorize?scope=wallet:user:email+wallet:user:read",
|
||||
token: "https://api.coinbase.com/oauth/token",
|
||||
userinfo: "https://api.coinbase.com/v2/user",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.data.id,
|
||||
name: profile.data.name,
|
||||
email: profile.data.email,
|
||||
image: profile.data.avatar_url,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
85
packages/core/src/providers/coinbase.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Coinbase</b> integration.</span>
|
||||
* <a href="https://coinbase.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/coinbase.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/coinbase
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add Coinbase login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/coinbase
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Coinbase from "@auth/core/providers/coinbase"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Coinbase({ clientId: COINBASE_CLIENT_ID, clientSecret: COINBASE_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Coinbase OAuth documentation](https://developers.coinbase.com/api/v2)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* :::tip
|
||||
* This Provider template has a 2 hour access token to it. A refresh token is also returned.
|
||||
* :::
|
||||
*
|
||||
* By default, Auth.js assumes that the Coinbase provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Coinbase provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/coinbase.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Coinbase(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "coinbase",
|
||||
name: "Coinbase",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://www.coinbase.com/oauth/authorize?scope=wallet:user:email+wallet:user:read",
|
||||
token: "https://api.coinbase.com/oauth/token",
|
||||
userinfo: "https://api.coinbase.com/v2/user",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.data.id,
|
||||
name: profile.data.name,
|
||||
email: profile.data.email,
|
||||
image: profile.data.avatar_url,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CommonProviderOptions } from "./index.js"
|
||||
import type { Awaitable, User } from "../types.js"
|
||||
import type { JSXInternal } from "preact/src/jsx.js"
|
||||
import type { JSX } from "preact"
|
||||
|
||||
/**
|
||||
* Besides providing type safety inside {@link CredentialsConfig.authorize}
|
||||
@@ -8,7 +8,7 @@ import type { JSXInternal } from "preact/src/jsx.js"
|
||||
* on the default sign in page.
|
||||
*/
|
||||
export interface CredentialInput
|
||||
extends Partial<JSXInternal.IntrinsicElements["input"]> {
|
||||
extends Partial<JSX.IntrinsicElements["input"]> {
|
||||
label?: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Discord</b> integration.</span>
|
||||
* <a href="https://discord.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/discord.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/discord
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
@@ -74,6 +84,54 @@ export interface DiscordProfile extends Record<string, any> {
|
||||
image_url: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Discord login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/discord
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Discord from "@auth/core/providers/discord"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Discord({ clientId: DISCORD_CLIENT_ID, clientSecret: DISCORD_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Discord OAuth documentation](https://discord.com/developers/docs/topics/oauth2)
|
||||
* - [Discord OAuth apps](https://discord.com/developers/applications)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Discord provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Discord provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/discord.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Discord<P extends DiscordProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* @param {import("../core").Provider} options
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* // pages/api/auth/[...nextauth].js
|
||||
* import Providers from `next-auth/providers`
|
||||
* ...
|
||||
* providers: [
|
||||
* Providers.Dropbox({
|
||||
* clientId: process.env.DROPBOX_CLIENT_ID,
|
||||
* clientSecret: process.env.DROPBOX_CLIENT_SECRET
|
||||
* })
|
||||
* ]
|
||||
* ...
|
||||
*
|
||||
* // pages/index
|
||||
* import { signIn } from "next-auth/react"
|
||||
* ...
|
||||
* <button onClick={() => signIn("dropbox")}>
|
||||
* Sign in
|
||||
* </button>
|
||||
* ...
|
||||
* ```
|
||||
* *Resources:*
|
||||
* - [NextAuth.js Documentation](https://authjs.dev/reference/oauth-providers/dropbox)
|
||||
* - [Dropbox Documentation](https://developers.dropbox.com/oauth-guide)
|
||||
* - [Configuration](https://www.dropbox.com/developers/apps)
|
||||
*/
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Dropbox(options) {
|
||||
return {
|
||||
id: "dropbox",
|
||||
name: "Dropbox",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://www.dropbox.com/oauth2/authorize?token_access_type=offline&scope=account_info.read",
|
||||
token: "https://api.dropboxapi.com/oauth2/token",
|
||||
userinfo: "https://api.dropboxapi.com/2/users/get_current_account",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.account_id,
|
||||
name: profile.name.display_name,
|
||||
email: profile.email,
|
||||
image: profile.profile_photo_url,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
81
packages/core/src/providers/dropbox.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Dropbox</b> integration.</span>
|
||||
* <a href="https://dropbox.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/dropbox.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/dropbox
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add Dropbox login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/dropbox
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Dropbox from "@auth/core/providers/dropbox"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Dropbox({ clientId: DROPBOX_CLIENT_ID, clientSecret: DROPBOX_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Dropbox OAuth documentation](https://developers.dropbox.com/oauth-guide)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Dropbox provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Dropbox provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/dropbox.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Dropbox(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "dropbox",
|
||||
name: "Dropbox",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://www.dropbox.com/oauth2/authorize?token_access_type=offline&scope=account_info.read",
|
||||
token: "https://api.dropboxapi.com/oauth2/token",
|
||||
userinfo: "https://api.dropboxapi.com/2/users/get_current_account",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.account_id,
|
||||
name: profile.name.display_name,
|
||||
email: profile.email,
|
||||
image: profile.profile_photo_url,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>DuendeIdentityServer6</b> integration.</span>
|
||||
* <a href="https://docs.duendesoftware.com/identityserver/v6">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/duende-identity-server6.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/duende-identity-server6
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./oauth.js"
|
||||
|
||||
export interface DuendeISUser extends Record<string, any> {
|
||||
@@ -7,6 +17,72 @@ export interface DuendeISUser extends Record<string, any> {
|
||||
verified: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Add DuendeIdentityServer6 login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/duende-identity-server6
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import DuendeIdentityServer6 from "@auth/core/providers/duende-identity-server6"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [DuendeIdentityServer6({ clientId: DIS6_CLIENT_ID, clientSecret: DIS6_CLIENT_SECRET, issuer: DIS6_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [DuendeIdentityServer6 documentation](https://docs.duendesoftware.com/identityserver/v6)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
*
|
||||
* ## Demo IdentityServer
|
||||
*
|
||||
* The configuration below is for the demo server at https://demo.duendesoftware.com/
|
||||
*
|
||||
* If you want to try it out, you can copy and paste the configuration below.
|
||||
*
|
||||
* You can sign in to the demo service with either <b>bob/bob</b> or <b>alice/alice</b>.
|
||||
*
|
||||
* ```js title=pages/api/auth/[...nextauth].js
|
||||
* import DuendeIDS6Provider from "next-auth/providers/duende-identity-server6"
|
||||
* providers: [
|
||||
* DuendeIDS6Provider({
|
||||
* clientId: "interactive.confidential",
|
||||
* clientSecret: "secret",
|
||||
* issuer: "https://demo.duendesoftware.com",
|
||||
* })
|
||||
* ]
|
||||
* ```
|
||||
* By default, Auth.js assumes that the DuendeIdentityServer6 provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The DuendeIdentityServer6 provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/duende-identity-server6.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function DuendeIdentityServer6<P extends DuendeISUser>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface SendVerificationRequestParams {
|
||||
* - [SendGrid](https://sendgrid.com)
|
||||
* - etc.
|
||||
*
|
||||
* @see [Custom email service with Auth.js](https://authjs.dev/guides/providers/email#custom-email-service)
|
||||
* [Custom email service with Auth.js](https://authjs.dev/guides/providers/email#custom-email-service)
|
||||
*/
|
||||
export interface EmailConfig extends CommonProviderOptions {
|
||||
type: "email"
|
||||
@@ -81,7 +81,238 @@ export interface EmailConfig extends CommonProviderOptions {
|
||||
// when started working on https://github.com/nextauthjs/next-auth/discussions/1465
|
||||
export type EmailProviderType = "email"
|
||||
|
||||
/** TODO: */
|
||||
/**
|
||||
* ## Overview
|
||||
* The Email provider uses email to send "magic links" that can be used to sign in, you will likely have seen these if you have used services like Slack before.
|
||||
*
|
||||
* Adding support for signing in via email in addition to one or more OAuth services provides a way for users to sign in if they lose access to their OAuth account (e.g. if it is locked or deleted).
|
||||
*
|
||||
* The Email provider can be used in conjunction with (or instead of) one or more OAuth providers.
|
||||
* ### How it works
|
||||
*
|
||||
* On initial sign in, a **Verification Token** is sent to the email address provided. By default this token is valid for 24 hours. If the Verification Token is used within that time (i.e. by clicking on the link in the email) an account is created for the user and they are signed in.
|
||||
*
|
||||
*
|
||||
* If someone provides the email address of an _existing account_ when signing in, an email is sent and they are signed into the account associated with that email address when they follow the link in the email.
|
||||
*
|
||||
* :::tip
|
||||
* The Email Provider can be used with both JSON Web Tokens and database sessions, but you **must** configure a database to use it. It is not possible to enable email sign in without using a database.
|
||||
* :::
|
||||
* ## Configuration
|
||||
|
||||
* 1. NextAuth.js does not include `nodemailer` as a dependency, so you'll need to install it yourself if you want to use the Email Provider. Run `npm install nodemailer` or `yarn add nodemailer`.
|
||||
* 2. You will need an SMTP account; ideally for one of the [services known to work with `nodemailer`](https://community.nodemailer.com/2-0-0-beta/setup-smtp/well-known-services/).
|
||||
* 3. There are two ways to configure the SMTP server connection.
|
||||
*
|
||||
* You can either use a connection string or a `nodemailer` configuration object.
|
||||
*
|
||||
* 3.1 **Using a connection string**
|
||||
*
|
||||
* Create an `.env` file to the root of your project and add the connection string and email address.
|
||||
*
|
||||
* ```js title=".env" {1}
|
||||
* EMAIL_SERVER=smtp://username:password@smtp.example.com:587
|
||||
* EMAIL_FROM=noreply@example.com
|
||||
* ```
|
||||
*
|
||||
* Now you can add the email provider like this:
|
||||
*
|
||||
* ```js {3} title="pages/api/auth/[...nextauth].js"
|
||||
* import EmailProvider from "next-auth/providers/email";
|
||||
* ...
|
||||
* providers: [
|
||||
* EmailProvider({
|
||||
* server: process.env.EMAIL_SERVER,
|
||||
* from: process.env.EMAIL_FROM
|
||||
* }),
|
||||
* ],
|
||||
* ```
|
||||
*
|
||||
* 3.2 **Using a configuration object**
|
||||
*
|
||||
* In your `.env` file in the root of your project simply add the configuration object options individually:
|
||||
*
|
||||
* ```js title=".env"
|
||||
* EMAIL_SERVER_USER=username
|
||||
* EMAIL_SERVER_PASSWORD=password
|
||||
* EMAIL_SERVER_HOST=smtp.example.com
|
||||
* EMAIL_SERVER_PORT=587
|
||||
* EMAIL_FROM=noreply@example.com
|
||||
* ```
|
||||
*
|
||||
* Now you can add the provider settings to the NextAuth.js options object in the Email Provider.
|
||||
*
|
||||
* ```js title="pages/api/auth/[...nextauth].js"
|
||||
* import EmailProvider from "next-auth/providers/email";
|
||||
* ...
|
||||
* providers: [
|
||||
* EmailProvider({
|
||||
* server: {
|
||||
* host: process.env.EMAIL_SERVER_HOST,
|
||||
* port: process.env.EMAIL_SERVER_PORT,
|
||||
* auth: {
|
||||
* user: process.env.EMAIL_SERVER_USER,
|
||||
* pass: process.env.EMAIL_SERVER_PASSWORD
|
||||
* }
|
||||
* },
|
||||
* from: process.env.EMAIL_FROM
|
||||
* }),
|
||||
* ],
|
||||
* ```
|
||||
*
|
||||
* 4. Do not forget to setup one of the database [adapters](https://authjs.dev/reference/adapters) for storing the Email verification token.
|
||||
*
|
||||
* 5. You can now sign in with an email address at `/api/auth/signin`.
|
||||
*
|
||||
* A user account (i.e. an entry in the Users table) will not be created for the user until the first time they verify their email address. If an email address is already associated with an account, the user will be signed in to that account when they use the link in the email.
|
||||
*
|
||||
* ## Customizing emails
|
||||
*
|
||||
* You can fully customize the sign in email that is sent by passing a custom function as the `sendVerificationRequest` option to `EmailProvider()`.
|
||||
*
|
||||
* e.g.
|
||||
*
|
||||
* ```js {3} title="pages/api/auth/[...nextauth].js"
|
||||
* import EmailProvider from "next-auth/providers/email";
|
||||
* ...
|
||||
* providers: [
|
||||
* EmailProvider({
|
||||
* server: process.env.EMAIL_SERVER,
|
||||
* from: process.env.EMAIL_FROM,
|
||||
* sendVerificationRequest({
|
||||
* identifier: email,
|
||||
* url,
|
||||
* provider: { server, from },
|
||||
* }) {
|
||||
* // your function
|
||||
* },
|
||||
* }),
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* The following code shows the complete source for the built-in `sendVerificationRequest()` method:
|
||||
*
|
||||
* ```js
|
||||
* import { createTransport } from "nodemailer"
|
||||
*
|
||||
* async function sendVerificationRequest(params) {
|
||||
* const { identifier, url, provider, theme } = params
|
||||
* const { host } = new URL(url)
|
||||
* // NOTE: You are not required to use `nodemailer`, use whatever you want.
|
||||
* const transport = createTransport(provider.server)
|
||||
* const result = await transport.sendMail({
|
||||
* to: identifier,
|
||||
* from: provider.from,
|
||||
* subject: `Sign in to ${host}`,
|
||||
* text: text({ url, host }),
|
||||
* html: html({ url, host, theme }),
|
||||
* })
|
||||
* const failed = result.rejected.concat(result.pending).filter(Boolean)
|
||||
* if (failed.length) {
|
||||
* throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`)
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* function html(params: { url: string; host: string; theme: Theme }) {
|
||||
* const { url, host, theme } = params
|
||||
*
|
||||
* const escapedHost = host.replace(/\./g, "​.")
|
||||
*
|
||||
* const brandColor = theme.brandColor || "#346df1"
|
||||
* const color = {
|
||||
* background: "#f9f9f9",
|
||||
* text: "#444",
|
||||
* mainBackground: "#fff",
|
||||
* buttonBackground: brandColor,
|
||||
* buttonBorder: brandColor,
|
||||
* buttonText: theme.buttonText || "#fff",
|
||||
* }
|
||||
*
|
||||
* return `
|
||||
* <body style="background: ${color.background};">
|
||||
* <table width="100%" border="0" cellspacing="20" cellpadding="0"
|
||||
* style="background: ${color.mainBackground}; max-width: 600px; margin: auto; border-radius: 10px;">
|
||||
* <tr>
|
||||
* <td align="center"
|
||||
* style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
||||
* Sign in to <strong>${escapedHost}</strong>
|
||||
* </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td align="center" style="padding: 20px 0;">
|
||||
* <table border="0" cellspacing="0" cellpadding="0">
|
||||
* <tr>
|
||||
* <td align="center" style="border-radius: 5px;" bgcolor="${color.buttonBackground}"><a href="${url}"
|
||||
* target="_blank"
|
||||
* style="font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: ${color.buttonText}; text-decoration: none; border-radius: 5px; padding: 10px 20px; border: 1px solid ${color.buttonBorder}; display: inline-block; font-weight: bold;">Sign
|
||||
* in</a></td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td align="center"
|
||||
* style="padding: 0px 0px 10px 0px; font-size: 16px; line-height: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
|
||||
* If you did not request this email you can safely ignore it.
|
||||
* </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </body>
|
||||
* `
|
||||
* }
|
||||
*
|
||||
* // Email Text body (fallback for email clients that don't render HTML, e.g. feature phones)
|
||||
* function text({ url, host }: { url: string; host: string }) {
|
||||
* return `Sign in to ${host}\n${url}\n\n`
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* :::tip
|
||||
* If you want to generate great looking email client compatible HTML with React, check out https://mjml.io
|
||||
* :::
|
||||
*
|
||||
* ## Customizing the Verification Token
|
||||
*
|
||||
* By default, we are generating a random verification token. You can define a `generateVerificationToken` method in your provider options if you want to override it:
|
||||
*
|
||||
* ```js title="pages/api/auth/[...nextauth].js"
|
||||
* providers: [
|
||||
* EmailProvider({
|
||||
* async generateVerificationToken() {
|
||||
* return "ABC123"
|
||||
* }
|
||||
* })
|
||||
* ],
|
||||
* ```
|
||||
*
|
||||
* ## Normalizing the email address
|
||||
*
|
||||
* By default, NextAuth.js will normalize the email address. It treats values as case-insensitive (which is technically not compliant to the [RFC 2821 spec](https://datatracker.ietf.org/doc/html/rfc2821), but in practice this causes more problems than it solves, eg. when looking up users by e-mail from databases.) and also removes any secondary email address that was passed in as a comma-separated list. You can apply your own normalization via the `normalizeIdentifier` method on the `EmailProvider`. The following example shows the default behavior:
|
||||
* ```ts
|
||||
* EmailProvider({
|
||||
* // ...
|
||||
* normalizeIdentifier(identifier: string): string {
|
||||
* // Get the first two elements only,
|
||||
* // separated by `@` from user input.
|
||||
* let [local, domain] = identifier.toLowerCase().trim().split("@")
|
||||
* // The part before "@" can contain a ","
|
||||
* // but we remove it on the domain part
|
||||
* domain = domain.split(",")[0]
|
||||
* return `${local}@${domain}`
|
||||
*
|
||||
* // You can also throw an error, which will redirect the user
|
||||
* // to the error page with error=EmailSignin in the URL
|
||||
* // if (identifier.split("@").length > 2) {
|
||||
* // throw new Error("Only one email allowed")
|
||||
* // }
|
||||
* },
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* :::warning
|
||||
* Always make sure this returns a single e-mail address, even if multiple ones were passed in.
|
||||
* :::
|
||||
*/
|
||||
export default function Email(config: EmailConfig): EmailConfig {
|
||||
return {
|
||||
id: "email",
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>EVEOnline</b> integration.</span>
|
||||
* <a href="https://eveonline.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/eveonline.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/eveonline
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface EVEOnlineProfile extends Record<string, any> {
|
||||
@@ -10,6 +20,73 @@ export interface EVEOnlineProfile extends Record<string, any> {
|
||||
IntellectualProperty: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add EveOnline login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/eveonline
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import EveOnline from "@auth/core/providers/eveonline"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [EveOnline({ clientId: EVEONLINE_CLIENT_ID, clientSecret: EVEONLINE_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [EveOnline OAuth documentation](https://developers.eveonline.com/blog/article/sso-to-authenticated-calls)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* :::tip
|
||||
* When creating your application, make sure to select `Authentication Only` as the connection type.
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
* If using JWT for the session, you can add the `CharacterID` to the JWT token and session. Example:
|
||||
* ```js
|
||||
* options: {
|
||||
* jwt: {
|
||||
* secret: process.env.JWT_SECRET,
|
||||
* },
|
||||
* callbacks: {
|
||||
* session: async ({ session, token }) => {
|
||||
* session.user.id = token.id;
|
||||
* return session;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* :::
|
||||
* By default, Auth.js assumes that the EveOnline provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The EveOnline provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/eveonline.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function EVEOnline<P extends EVEOnlineProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Facebook</b> integration.</span>
|
||||
* <a href="https://facebook.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/facebook.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/facebook
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
interface FacebookPictureData {
|
||||
@@ -12,6 +22,61 @@ export interface FacebookProfile extends Record<string, any> {
|
||||
picture: FacebookPicture
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Facebook login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/facebook
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Facebook from "@auth/core/providers/facebook"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Facebook({ clientId: FACEBOOK_CLIENT_ID, clientSecret: FACEBOOK_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Facebook OAuth documentation](https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* :::tip
|
||||
* Production applications cannot use localhost URLs to sign in with Facebook. You need to use a dedicated development application in Facebook to use localhost callback URLs.
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
* Email address may not be returned for accounts created on mobile.
|
||||
* :::
|
||||
*
|
||||
* By default, Auth.js assumes that the Facebook provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Facebook provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/facebook.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Facebook<P extends FacebookProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function FACEIT(options) {
|
||||
return {
|
||||
id: "faceit",
|
||||
name: "FACEIT",
|
||||
type: "oauth",
|
||||
authorization: "https://accounts.faceit.com/accounts?redirect_popup=true",
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${options.clientId}:${options.clientSecret}`
|
||||
).toString("base64")}`,
|
||||
},
|
||||
token: "https://api.faceit.com/auth/v1/oauth/token",
|
||||
userinfo: "https://api.faceit.com/auth/v1/resources/userinfo",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.guid,
|
||||
name: profile.name,
|
||||
email: profile.email,
|
||||
image: profile.picture,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
88
packages/core/src/providers/faceit.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>FACEIT</b> integration.</span>
|
||||
* <a href="https://faceit.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/faceit.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/faceit
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add FACEIT login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/faceit
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import FACEIT from "@auth/core/providers/faceit"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [FACEIT({ clientId: FACEIT_CLIENT_ID, clientSecret: FACEIT_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [FACEIT OAuth documentation](https://cdn.faceit.com/third_party/docs/FACEIT_Connect_3.0.pdf)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* Grant type: Authorization Code
|
||||
* Scopes to have basic infos (email, nickname, guid and avatar) : openid, email, profile
|
||||
* By default, Auth.js assumes that the FACEIT provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The FACEIT provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/faceit.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function FACEIT(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "faceit",
|
||||
name: "FACEIT",
|
||||
type: "oauth",
|
||||
authorization: "https://accounts.faceit.com/accounts?redirect_popup=true",
|
||||
// @ts-expect-error - TODO fix this
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(
|
||||
`${options.clientId}:${options.clientSecret}`
|
||||
).toString("base64")}`,
|
||||
},
|
||||
token: "https://api.faceit.com/auth/v1/oauth/token",
|
||||
userinfo: "https://api.faceit.com/auth/v1/resources/userinfo",
|
||||
profile(profile) {
|
||||
return {
|
||||
id: profile.guid,
|
||||
name: profile.name,
|
||||
email: profile.email,
|
||||
image: profile.picture,
|
||||
}
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Foursquare(options) {
|
||||
const { apiVersion = "20230131" } = options
|
||||
return {
|
||||
id: "foursquare",
|
||||
name: "Foursquare",
|
||||
type: "oauth",
|
||||
authorization: "https://foursquare.com/oauth2/authenticate",
|
||||
token: "https://foursquare.com/oauth2/access_token",
|
||||
userinfo: {
|
||||
url: `https://api.foursquare.com/v2/users/self?v=${apiVersion}`,
|
||||
request({ tokens, provider }) {
|
||||
const url = new URL(provider.userinfo.url)
|
||||
url.searchParams.append("oauth_token", tokens.access_token)
|
||||
return fetch(url).then((res) => res.json())
|
||||
},
|
||||
},
|
||||
profile({ response: { user: profile } }) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: `${profile.firstName} ${profile.lastName}`,
|
||||
email: profile.contact.email,
|
||||
image: profile.photo
|
||||
? `${profile.photo.prefix}original${profile.photo.suffix}`
|
||||
: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/foursquare.svg",
|
||||
logoDark: "/foursquare-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#000",
|
||||
bgDark: "#000",
|
||||
textDark: "#fff",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
102
packages/core/src/providers/foursquare.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>FourSquare</b> integration.</span>
|
||||
* <a href="https://foursquare.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/foursquare.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/foursquare
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add FourSquare login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/foursquare
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import FourSquare from "@auth/core/providers/foursquare"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [FourSquare({ clientId: FOURSQUARE_CLIENT_ID, clientSecret: FOURSQUARE_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [FourSquare OAuth documentation](https://developer.foursquare.com/docs/places-api/authentication/#web-applications)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the FourSquare provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::warning
|
||||
* Foursquare requires an additional apiVersion parameter in YYYYMMDD format, which essentially states "I'm prepared for API changes up to this date".
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The FourSquare provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/foursquare.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Foursquare(
|
||||
options: OAuthUserConfig<Record<string, any>> & { apiVersion?: string }
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
const { apiVersion = "20230131" } = options
|
||||
return {
|
||||
id: "foursquare",
|
||||
name: "Foursquare",
|
||||
type: "oauth",
|
||||
authorization: "https://foursquare.com/oauth2/authenticate",
|
||||
token: "https://foursquare.com/oauth2/access_token",
|
||||
userinfo: {
|
||||
url: `https://api.foursquare.com/v2/users/self?v=${apiVersion}`,
|
||||
request({ tokens, provider }) {
|
||||
const url = new URL(provider.userinfo?.url!)
|
||||
url.searchParams.append("oauth_token", tokens.access_token!)
|
||||
return fetch(url).then((res) => res.json())
|
||||
},
|
||||
},
|
||||
profile({ response: { user: profile } }) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: `${profile.firstName} ${profile.lastName}`,
|
||||
email: profile.contact.email,
|
||||
image: profile.photo
|
||||
? `${profile.photo.prefix}original${profile.photo.suffix}`
|
||||
: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/foursquare.svg",
|
||||
logoDark: "/foursquare-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#000",
|
||||
bgDark: "#000",
|
||||
textDark: "#fff",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Freshbooks(options) {
|
||||
return {
|
||||
id: "freshbooks",
|
||||
name: "Freshbooks",
|
||||
type: "oauth",
|
||||
authorization: "https://auth.freshbooks.com/service/auth/oauth/authorize",
|
||||
token: "https://api.freshbooks.com/auth/oauth/token",
|
||||
userinfo: "https://api.freshbooks.com/auth/api/v1/users/me",
|
||||
async profile(profile) {
|
||||
return {
|
||||
id: profile.response.id,
|
||||
name: `${profile.response.first_name} ${profile.response.last_name}`,
|
||||
email: profile.response.email,
|
||||
image: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/freshbooks.svg",
|
||||
logoDark: "/freshbooks-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#0075dd",
|
||||
bgDark: "#0075dd",
|
||||
textDark: "#fff",
|
||||
},
|
||||
...options,
|
||||
}
|
||||
}
|
||||
89
packages/core/src/providers/freshbooks.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>FreshBooks</b> integration.</span>
|
||||
* <a href="https://freshbooks.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/freshbooks.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/freshbooks
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add FreshBooks login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/freshbooks
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import FreshBooks from "@auth/core/providers/freshbooks"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [FreshBooks({ clientId: FRESHBOOKS_CLIENT_ID, clientSecret: FRESHBOOKS_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [FreshBooks OAuth documentation](https://www.freshbooks.com/api/authenticating-with-oauth-2-0-on-the-new-freshbooks-api
|
||||
)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the FreshBooks provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The FreshBooks provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/freshbooks.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Freshbooks(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "freshbooks",
|
||||
name: "Freshbooks",
|
||||
type: "oauth",
|
||||
authorization: "https://auth.freshbooks.com/service/auth/oauth/authorize",
|
||||
token: "https://api.freshbooks.com/auth/oauth/token",
|
||||
userinfo: "https://api.freshbooks.com/auth/api/v1/users/me",
|
||||
async profile(profile) {
|
||||
return {
|
||||
id: profile.response.id,
|
||||
name: `${profile.response.first_name} ${profile.response.last_name}`,
|
||||
email: profile.response.email,
|
||||
image: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/freshbooks.svg",
|
||||
logoDark: "/freshbooks-dark.svg",
|
||||
bg: "#fff",
|
||||
text: "#0075dd",
|
||||
bgDark: "#0075dd",
|
||||
textDark: "#fff",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>FusionAuth</b> integration.</span>
|
||||
* <a href="https://fusionauth.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/fushionauth.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/fushionauth
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./oauth.js"
|
||||
|
||||
/**
|
||||
@@ -21,6 +31,73 @@ export interface FusionAuthProfile extends Record<string, any> {
|
||||
sid: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add FusionAuth login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/fusionauth
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import FusionAuth from "@auth/core/providers/fusionauth"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [FusionAuth({ clientId: FUSIONAUTH_CLIENT_ID, clientSecret: FUSIONAUTH_CLIENT_SECRET, tenantId: FUSIONAUTH_TENANT_ID, issuer: FUSIONAUTH_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
* :::warning
|
||||
* If you're using multi-tenancy, you need to pass in the tenantId option to apply the proper theme.
|
||||
* :::
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [FusionAuth OAuth documentation](https://fusionauth.io/docs/v1/tech/oauth/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the FusionAuth provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* ## Configuration
|
||||
* :::tip
|
||||
* An application can be created at https://your-fusionauth-server-url/admin/application.
|
||||
*
|
||||
* For more information, follow the [FusionAuth 5-minute setup guide](https://fusionauth.io/docs/v1/tech/5-minute-setup-guide).
|
||||
* :::
|
||||
*
|
||||
* In the OAuth settings for your application, configure the following.
|
||||
*
|
||||
* - Redirect URL
|
||||
* - https://localhost:3000/api/auth/callback/fusionauth
|
||||
* - Enabled grants
|
||||
* - Make sure _Authorization Code_ is enabled.
|
||||
*
|
||||
* If using JSON Web Tokens, you need to make sure the signing algorithm is RS256, you can create an RS256 key pair by
|
||||
* going to Settings, Key Master, generate RSA and choosing SHA-256 as algorithm. After that, go to the JWT settings of
|
||||
* your application and select this key as Access Token signing key and Id Token signing key.
|
||||
* :::tip
|
||||
*
|
||||
* The FusionAuth provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/fusionauth.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function FusionAuth<P extends FusionAuthProfile>(
|
||||
// tenantId only needed if there is more than one tenant configured on the server
|
||||
options: OAuthUserConfig<P> & { tenantId?: string }
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* ---
|
||||
* @module providers/github
|
||||
*/
|
||||
|
||||
@@ -71,27 +70,33 @@ export interface GitHubProfile {
|
||||
/**
|
||||
* Add GitHub login to your page and make requests to [GitHub APIs](https://docs.github.com/en/rest).
|
||||
*
|
||||
* ## Example
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/github
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
* ```ts
|
||||
* import { Auth } from "@auth/core"
|
||||
* import GitHub from "@auth/core/providers/github"
|
||||
*
|
||||
* const request = new Request("https://example.com")
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [GitHub({ clientId: "", clientSecret: "" })],
|
||||
* providers: [GitHub({ clientId: GITHUB_CLIENT_ID, clientSecret: GITHUB_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ## Resources
|
||||
* ### Resources
|
||||
*
|
||||
* @see [GitHub - Creating an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)
|
||||
* @see [GitHub - Authorizing OAuth Apps](https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps)
|
||||
* @see [GitHub - Configure your GitHub OAuth Apps](https://github.com/settings/developers)
|
||||
* @see [Learn more about OAuth](https://authjs.dev/concepts/oauth)
|
||||
* @see [Source code](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/github.ts)
|
||||
* - [GitHub - Creating an OAuth App](https://docs.github.com/en/developers/apps/building-oauth-apps/creating-an-oauth-app)
|
||||
* - [GitHub - Authorizing OAuth Apps](https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps)
|
||||
* - [GitHub - Configure your GitHub OAuth Apps](https://github.com/settings/developers)
|
||||
* - [Learn more about OAuth](https://authjs.dev/concepts/oauth)
|
||||
* - [Source code](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/github.ts)
|
||||
*
|
||||
* ## Notes
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the GitHub provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
@@ -129,14 +134,20 @@ export default function GitHub(
|
||||
url: "https://api.github.com/user",
|
||||
async request({ tokens, provider }) {
|
||||
const profile = await fetch(provider.userinfo?.url as URL, {
|
||||
headers: { Authorization: `Bearer ${tokens.access_token}`, 'User-Agent': 'authjs' },
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens.access_token}`,
|
||||
"User-Agent": "authjs",
|
||||
},
|
||||
}).then(async (res) => await res.json())
|
||||
|
||||
if (!profile.email) {
|
||||
// If the user does not have a public email, get another via the GitHub API
|
||||
// See https://docs.github.com/en/rest/users/emails#list-public-email-addresses-for-the-authenticated-user
|
||||
const res = await fetch("https://api.github.com/user/emails", {
|
||||
headers: { Authorization: `Bearer ${tokens.access_token}`, 'User-Agent': 'authjs' },
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens.access_token}`,
|
||||
"User-Agent": "authjs",
|
||||
},
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>GitLab</b> integration.</span>
|
||||
* <a href="https://gitlab.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/gitlab.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/gitlab
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface GitLabProfile extends Record<string, any> {
|
||||
@@ -48,32 +58,38 @@ export interface GitLabProfile extends Record<string, any> {
|
||||
/**
|
||||
* Add GitLab login to your page.
|
||||
*
|
||||
* ## Example
|
||||
* ### Setup
|
||||
*
|
||||
* @example
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/gitlab
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import GitLab from "@auth/core/providers/gitlab"
|
||||
*
|
||||
* const request = new Request("https://example.com")
|
||||
* const response = await AuthHandler(request, {
|
||||
* providers: [
|
||||
* GitLab({clientId: "", clientSecret: ""})
|
||||
* ]
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [GitLab({ clientId: GITLAB_CLIENT_ID, clientSecret: GITLAB_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ## Resources
|
||||
* ### Resources
|
||||
*
|
||||
* @see [Link 1](https://example.com)
|
||||
* - [GitLab OAuth documentation](https://docs.gitlab.com/ee/api/oauth2.html)
|
||||
*
|
||||
* ## Notes
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the GitLab provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
* Enable the `read_user` option in scope if you want to save the users email address on sign up.
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The GitLab provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/gitlab.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Google</b> integration.</span>
|
||||
* <a href="https://google.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/google.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/google
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface GoogleProfile extends Record<string, any> {
|
||||
@@ -18,6 +28,111 @@ export interface GoogleProfile extends Record<string, any> {
|
||||
sub: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Google login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/google
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Google from "@auth/core/providers/google"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Google({ clientId: GOOGLE_CLIENT_ID, clientSecret: GOOGLE_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Google OAuth documentation](https://developers.google.com/identity/protocols/oauth2)
|
||||
* - [Google OAuth Configuration](https://console.developers.google.com/apis/credentials)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Google provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
*
|
||||
* The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path. For example;
|
||||
*
|
||||
* - For production: `https://{YOUR_DOMAIN}/api/auth/callback/google`
|
||||
* - For development: `http://localhost:3000/api/auth/callback/google`
|
||||
*
|
||||
* :::warning
|
||||
* Google only provides Refresh Token to an application the first time a user signs in.
|
||||
*
|
||||
* To force Google to re-issue a Refresh Token, the user needs to remove the application from their account and sign in again:
|
||||
* https://myaccount.google.com/permissions
|
||||
*
|
||||
* Alternatively, you can also pass options in the `params` object of `authorization` which will force the Refresh Token to always be provided on sign in, however this will ask all users to confirm if they wish to grant your application access every time they sign in.
|
||||
*
|
||||
* If you need access to the RefreshToken or AccessToken for a Google account and you are not using a database to persist user accounts, this may be something you need to do.
|
||||
*
|
||||
* ```js title="pages/api/auth/[...nextauth].js"
|
||||
* const options = {
|
||||
* providers: [
|
||||
* GoogleProvider({
|
||||
* clientId: process.env.GOOGLE_ID,
|
||||
* clientSecret: process.env.GOOGLE_SECRET,
|
||||
* authorization: {
|
||||
* params: {
|
||||
* prompt: "consent",
|
||||
* access_type: "offline",
|
||||
* response_type: "code"
|
||||
* }
|
||||
* }
|
||||
* })
|
||||
* ],
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
* Google also returns a `email_verified` boolean property in the OAuth profile.
|
||||
*
|
||||
* You can use this property to restrict access to people with verified accounts at a particular domain.
|
||||
*
|
||||
* ```js
|
||||
* const options = {
|
||||
* ...
|
||||
* callbacks: {
|
||||
* async signIn({ account, profile }) {
|
||||
* if (account.provider === "google") {
|
||||
* return profile.email_verified && profile.email.endsWith("@example.com")
|
||||
* }
|
||||
* return true // Do different verification for other providers that don't have `email_verified`
|
||||
* },
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* :::
|
||||
* :::tip
|
||||
*
|
||||
* The Google provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/google.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Google<P extends GoogleProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>HubSpot</b> integration.</span>
|
||||
* <a href="https://hubspot.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/hubspot.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/hubspot
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
interface HubSpotProfile extends Record<string, any> {
|
||||
@@ -8,6 +18,57 @@ interface HubSpotProfile extends Record<string, any> {
|
||||
hub_id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Add HubSpot login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/hubspot
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import HubSpot from "@auth/core/providers/hubspot"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [HubSpot({ clientId: HUBSPOT_CLIENT_ID, clientSecret: HUBSPOT_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [HubSpot OAuth documentation](https://developers.hubspot.com/docs/api/oauth-quickstart-guide)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the HubSpot provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* You need to have an APP in your Developer Account as described at https://developers.hubspot.com/docs/api/developer-tools-overview
|
||||
* :::note
|
||||
* HubSpot returns a limited amount of information on the token holder (see [docs](https://legacydocs.hubspot.com/docs/methods/oauth2/get-access-token-information)). One other issue is that the name and profile photo cannot be fetched through API as discussed [here](https://community.hubspot.com/t5/APIs-Integrations/Profile-photo-is-not-retrieved-with-User-API/m-p/325521).
|
||||
* :::
|
||||
* :::tip
|
||||
*
|
||||
* The HubSpot provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/hubspot.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function HubSpot<P extends HubSpotProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function IdentityServer4(options) {
|
||||
return {
|
||||
id: "identity-server4",
|
||||
name: "IdentityServer4",
|
||||
type: "oidc",
|
||||
options,
|
||||
}
|
||||
}
|
||||
72
packages/core/src/providers/identity-server4.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>IdentityServer4</b> integration.</span>
|
||||
* <a href="https://identityserver4.readthedocs.io">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/identity-server4.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/identity-server4
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add IdentityServer4 login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/identity-server4
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import IdentityServer4 from "@auth/core/providers/identity-server4"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [IdentityServer4({ clientId: IDENTITY_SERVER4_CLIENT_ID, clientSecret: IDENTITY_SERVER4_CLIENT_SECRET, issuer: IDENTITY_SERVER4_ISSUER })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [IdentityServer4 OAuth documentation](https://identityserver4.readthedocs.io/en/latest/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the IdentityServer4 provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::warning
|
||||
* IdentityServer4 is discontinued and only releases security updates until November 2022. You should consider an alternative provider.
|
||||
* :::
|
||||
* :::tip
|
||||
*
|
||||
* The IdentityServer4 provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/identity-server4.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function IdentityServer4(
|
||||
options: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "identity-server4",
|
||||
name: "IdentityServer4",
|
||||
type: "oidc",
|
||||
options,
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/**
|
||||
* @type {import("src/providers").OAuthProvider} options
|
||||
* @example
|
||||
*
|
||||
* ```js
|
||||
* // pages/api/auth/[...nextauth].js
|
||||
* import Providers from `next-auth/providers`
|
||||
* ...
|
||||
* providers: [
|
||||
* Providers.Instagram({
|
||||
* clientId: process.env.INSTAGRAM_CLIENT_ID,
|
||||
* clientSecret: process.env.INSTAGRAM_CLIENT_SECRET
|
||||
* })
|
||||
* ]
|
||||
* ...
|
||||
*
|
||||
* // pages/index
|
||||
* import { signIn } from "next-auth/react"
|
||||
* ...
|
||||
* <button onClick={() => signIn("instagram")}>
|
||||
* Sign in
|
||||
* </button>
|
||||
* ...
|
||||
* ```
|
||||
* [NextAuth.js Documentation](https://authjs.dev/reference/providers/instagram) | [Instagram Documentation](https://developers.facebook.com/docs/instagram-basic-display-api/getting-started) | [Configuration](https://developers.facebook.com/apps)
|
||||
*/
|
||||
/** @type {import(".").OAuthProvider} */
|
||||
export default function Instagram(options) {
|
||||
return {
|
||||
id: "instagram",
|
||||
name: "Instagram",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://api.instagram.com/oauth/authorize?scope=user_profile",
|
||||
token: "https://api.instagram.com/oauth/access_token",
|
||||
userinfo:
|
||||
"https://graph.instagram.com/me?fields=id,username,account_type,name",
|
||||
client: {
|
||||
token_endpoint_auth_method: "client_secret_post",
|
||||
},
|
||||
async profile(profile) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.username,
|
||||
email: null,
|
||||
image: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/instagram.svg",
|
||||
logoDark: "/instagram.svg",
|
||||
bg: "#fff",
|
||||
text: "#000",
|
||||
bgDark: "#fff",
|
||||
textDark: "#000",
|
||||
},
|
||||
options,
|
||||
}
|
||||
}
|
||||
102
packages/core/src/providers/instagram.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Instagram</b> integration.</span>
|
||||
* <a href="https://www.instagram.com/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/instagram.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/instagram
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
/**
|
||||
* Add Instagram login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/instagram
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Instagram from "@auth/core/providers/instagram"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Instagram({ clientId: INSTAGRAM_CLIENT_ID, clientSecret: INSTAGRAM_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Instagram OAuth documentation](https://developers.facebook.com/docs/instagram-basic-display-api/getting-started)
|
||||
* - [Instagram OAuth apps](https://developers.facebook.com/apps/)
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Instagram provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
*
|
||||
* :::warning
|
||||
* Email address is not returned by the Instagram API.
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
* Instagram display app required callback URL to be configured in your Facebook app and Facebook required you to use **https** even for localhost! In order to do that, you either need to [add an SSL to your localhost](https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/) or use a proxy such as [ngrok](https://ngrok.com/docs).
|
||||
* :::
|
||||
* :::tip
|
||||
*
|
||||
* The Instagram provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/instagram.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Instagram(
|
||||
config: OAuthUserConfig<Record<string, any>>
|
||||
): OAuthConfig<Record<string, any>> {
|
||||
return {
|
||||
id: "instagram",
|
||||
name: "Instagram",
|
||||
type: "oauth",
|
||||
authorization:
|
||||
"https://api.instagram.com/oauth/authorize?scope=user_profile",
|
||||
token: "https://api.instagram.com/oauth/access_token",
|
||||
userinfo:
|
||||
"https://graph.instagram.com/me?fields=id,username,account_type,name",
|
||||
client: {
|
||||
token_endpoint_auth_method: "client_secret_post",
|
||||
},
|
||||
async profile(profile) {
|
||||
return {
|
||||
id: profile.id,
|
||||
name: profile.username,
|
||||
email: null,
|
||||
image: null,
|
||||
}
|
||||
},
|
||||
style: {
|
||||
logo: "/instagram.svg",
|
||||
logoDark: "/instagram.svg",
|
||||
bg: "#fff",
|
||||
text: "#000",
|
||||
bgDark: "#fff",
|
||||
textDark: "#000",
|
||||
},
|
||||
options: config,
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Kakao</b> integration.</span>
|
||||
* <a href="https://www.kakaocorp.com/page/">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/kakao.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/kakao
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export type DateTime = string
|
||||
@@ -67,6 +77,57 @@ export interface KakaoProfile extends Record<string, any> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Kakao login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/kakao
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Kakao from "@auth/core/providers/kakao"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Kakao({ clientId: KAKAO_CLIENT_ID, clientSecret: KAKAO_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Kakao OAuth documentation](https://developers.kakao.com/product/kakaoLogin)
|
||||
* - [Kakao OAuth configuration](https://developers.kakao.com/docs/latest/en/kakaologin/common)
|
||||
*
|
||||
* ## Configuration
|
||||
* Create a provider and a Kakao application at https://developers.kakao.com/console/app. In the settings of the app under Kakao Login, activate web app, change consent items and configure callback URL.
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Kakao provider is
|
||||
* based on the [OAuth 2](https://www.rfc-editor.org/rfc/rfc6749.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Kakao provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/kakao.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Kakao<P extends KakaoProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>Keycloak</b> integration.</span>
|
||||
* <a href="https://keycloak.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/keycloak.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/keycloak
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface KeycloakProfile extends Record<string, any> {
|
||||
@@ -24,6 +34,64 @@ export interface KeycloakProfile extends Record<string, any> {
|
||||
user: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Keycloak login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/keycloak
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import Keycloak from "@auth/core/providers/keycloak"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [Keycloak({ clientId: KEYCLOAK_CLIENT_ID, clientSecret: KEYCLOAK_CLIENT_SECRET, issuer: KEYCLOAK_ISSUER, })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [Keycloak OIDC documentation](https://www.keycloak.org/docs/latest/server_admin/#_oidc_clients)
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* Create an openid-connect client in Keycloak with "confidential" as the "Access Type".
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::note
|
||||
*
|
||||
* issuer should include the realm – e.g. https://my-keycloak-domain.com/realms/My_Realm
|
||||
*
|
||||
* :::
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the Keycloak provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The Keycloak provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/keycloak.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function Keycloak<P extends KeycloakProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/**
|
||||
* <div style={{backgroundColor: "#000", display: "flex", justifyContent: "space-between", color: "#fff", padding: 16}}>
|
||||
* <span>Built-in <b>LINE</b> integration.</span>
|
||||
* <a href="https://LINE.com">
|
||||
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/line.svg" height="48" width="48"/>
|
||||
* </a>
|
||||
* </div>
|
||||
*
|
||||
* @module providers/line
|
||||
*/
|
||||
import type { OAuthConfig, OAuthUserConfig } from "./index.js"
|
||||
|
||||
export interface LineProfile extends Record<string, any> {
|
||||
@@ -12,6 +22,63 @@ export interface LineProfile extends Record<string, any> {
|
||||
user: any
|
||||
}
|
||||
|
||||
/**
|
||||
* Add LINE login to your page.
|
||||
*
|
||||
* ### Setup
|
||||
*
|
||||
* #### Callback URL
|
||||
* ```
|
||||
* https://example.com/api/auth/callback/line
|
||||
* ```
|
||||
*
|
||||
* #### Configuration
|
||||
*```js
|
||||
* import Auth from "@auth/core"
|
||||
* import LINE from "@auth/core/providers/line"
|
||||
*
|
||||
* const request = new Request(origin)
|
||||
* const response = await Auth(request, {
|
||||
* providers: [LINE({ clientId: LINE_CLIENT_ID, clientSecret: LINE_CLIENT_SECRET })],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* ### Resources
|
||||
*
|
||||
* - [LINE Login documentation](https://developers.line.biz/en/docs/line-login/integrate-line-login/)
|
||||
* - [LINE app console](https://developers.line.biz/console/)
|
||||
*
|
||||
* ## Configuration
|
||||
* Create a provider and a LINE login channel at https://developers.line.biz/console/. In the settings of the channel under LINE Login, activate web app and configure the following: Callback URL `http://localhost:3000/api/auth/callback/line`
|
||||
*
|
||||
* ### Notes
|
||||
*
|
||||
* By default, Auth.js assumes that the LINE provider is
|
||||
* based on the [Open ID Connect](https://openid.net/specs/openid-connect-core-1_0.html) specification.
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* To retrieve email address, you need to apply for Email address permission. Open [Line Developer Console](https://developers.line.biz/console/), go to your Login Channel. Scroll down bottom to find **OpenID Connect** -> **Email address permission**. Click **Apply** and follow the instruction.
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::tip
|
||||
*
|
||||
* The LINE provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/line.ts).
|
||||
* To override the defaults for your use case, check out [customizing a built-in OAuth provider](https://authjs.dev/guides/providers/custom-provider#override-default-options).
|
||||
*
|
||||
* :::
|
||||
*
|
||||
* :::info **Disclaimer**
|
||||
*
|
||||
* If you think you found a bug in the default configuration, you can [open an issue](https://authjs.dev/new/provider-issue).
|
||||
*
|
||||
* Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from
|
||||
* the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec,
|
||||
* we might not pursue a resolution. You can ask for more help in [Discussions](https://authjs.dev/new/github-discussions).
|
||||
*
|
||||
* :::
|
||||
*/
|
||||
export default function LINE<P extends LineProfile>(
|
||||
options: OAuthUserConfig<P>
|
||||
): OAuthConfig<P> {
|
||||
|
||||