Compare commits

...

21 Commits

Author SHA1 Message Date
GitHub Actions
e459d2d7e2 chore(release): bump package version(s) [skip ci] 2023-07-18 14:40:11 +00:00
Thang Vu
db1fd9007c fix(ts): types in sveltekit 2023-07-18 21:29:04 +07:00
Thang Vu
0439fc5fc6 feat(providers): add request param to sendVerificationRequest (#8071)
Co-authored-by: Corey Jepperson <11298888+acoreyj@users.noreply.github.com>
2023-07-18 15:39:11 +02:00
Benjamin Tamasi
d0dd2ababc fix(sveltekit): prefix for getSession url (#6478)
* [SvelteKit] fix getSession url

remove `/api` prefix from getSession function.

* Update packages/frameworks-sveltekit/src/lib/index.ts

---------

Co-authored-by: Thang Vu <hi@thvu.dev>
2023-07-16 21:01:25 +07:00
Thang Vu
ba58d48dba fix(providers): add authorization params for AzureAD (#8047)
https: //github.com/nextauthjs/next-auth/pull/5668

Co-authored-by: Andres Jose Sebastian Rincon Gonzalez <2531975+stianrincon@users.noreply.github.com>
2023-07-15 22:01:24 +07:00
Thang Vu
a8d76ed440 fix(ts): require id for updateUser param (#8044)
https: //github.com/nextauthjs/next-auth/pull/5431

Co-authored-by: Yuri Sulyma <453486+ysulyma@users.noreply.github.com>
2023-07-15 17:18:15 +07:00
Thang Vu
3d7b8720db chore(docs): OIDC example for BoxyHQ (#8032)
chore(docs): OIDC example for BoxyHQ

Co-authored-by: Deepak Prabhakara <deepak@boxyhq.com>
2023-07-13 23:43:10 +07:00
Francis Gulotta
1e886b97bc fix(EmailProvider): proper required fields and allow all nodemailer types (#8016) 2023-07-11 18:01:47 +02:00
Tal Aharoni
ecb14ccecd fix: correct Descope provider config (#8003) 2023-07-11 12:51:32 +02:00
GitHub Actions
8cee24d4ab chore(release): bump package version(s) [skip ci] 2023-07-10 19:40:53 +00:00
Balázs Orbán
0189a197be chore: fix syntax in package.json 2023-07-10 21:29:38 +02:00
Balázs Orbán
c44bf75c65 fix: add svelte as peer dependency
Fixes #8004
2023-07-10 21:27:16 +02:00
GitHub Actions
cf13b6c7e3 chore(release): bump package version(s) [skip ci] 2023-07-10 16:21:19 +00:00
Dahoom152
dc1a79e547 fix: drop svelte as peer dependency (#7989)
* optionally bumped to svelte 4.0

* removed redundancy

* Update package.json

* Update package.json

---------

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2023-07-10 18:10:29 +02:00
arjun
78964c115b fix(adapters): add missing .js file extension (#7971)
Add missing .js file extension
2023-07-07 17:05:07 +02:00
Balázs Orbán
7fa51e2a61 docs: clarify preview deployment guide 2023-07-06 16:44:31 +02:00
Gwenaël Gallon
a79774f6e8 fix(docs): fix catch-all route path (#7925) 2023-07-01 01:36:23 +02:00
Fatih Solhan
f779f05906 docs: remove extra 'if' in comment (#7914) 2023-06-30 21:00:28 +02:00
GitHub Actions
3245c02eac chore(release): bump package version(s) [skip ci] 2023-06-27 15:22:02 +00:00
Doron Sharon
a8dfc8ebb1 feat(providers): Add Descope provider (#7874)
* Add Descope provider

* Add Descope provider

* Remove dark logo, remove wellKnown, and fix user profile syntax

* Change to DESCOPE_SECRET

* Fix env comment

* Fix clientId extracting

* Change to client id
2023-06-26 18:18:58 +02:00
Esteve
1b80a18dd4 fix(adapters): Add .js file extension to relative imports (#7856)
Add .js file extension to relative imports
2023-06-24 10:21:50 +02:00
32 changed files with 343 additions and 81 deletions

View File

@@ -37,6 +37,7 @@ body:
- "Bungie" - "Bungie"
- "Cognito" - "Cognito"
- "Coinbase" - "Coinbase"
- "Descope"
- "Discord" - "Discord"
- "Dropbox" - "Dropbox"
- "EVE Online" - "EVE Online"

View File

@@ -13,6 +13,9 @@ AUTH0_ID=
AUTH0_SECRET= AUTH0_SECRET=
AUTH0_ISSUER= AUTH0_ISSUER=
DESCOPE_ID=
DESCOPE_SECRET=
KEYCLOAK_ID= KEYCLOAK_ID=
KEYCLOAK_SECRET= KEYCLOAK_SECRET=
KEYCLOAK_ISSUER= KEYCLOAK_ISSUER=

View File

@@ -22,6 +22,9 @@ BEYOND_IDENTITY_CLIENT_ID=
BEYOND_IDENTITY_CLIENT_SECRET= BEYOND_IDENTITY_CLIENT_SECRET=
BEYOND_IDENTITY_ISSUER= BEYOND_IDENTITY_ISSUER=
DESCOPE_ID=
DESCOPE_SECRET=
GITHUB_ID= GITHUB_ID=
GITHUB_SECRET= GITHUB_SECRET=

View File

@@ -10,6 +10,7 @@ import BeyondIdentity from "@auth/core/providers/beyondidentity"
import BoxyHQSAML from "@auth/core/providers/boxyhq-saml" import BoxyHQSAML from "@auth/core/providers/boxyhq-saml"
// import Cognito from "@auth/core/providers/cognito" // import Cognito from "@auth/core/providers/cognito"
import Credentials from "@auth/core/providers/credentials" import Credentials from "@auth/core/providers/credentials"
import Descope from "@auth/core/providers/descope"
import Discord from "@auth/core/providers/discord" import Discord from "@auth/core/providers/discord"
import DuendeIDS6 from "@auth/core/providers/duende-identity-server6" import DuendeIDS6 from "@auth/core/providers/duende-identity-server6"
// import Email from "@auth/core/providers/email" // import Email from "@auth/core/providers/email"
@@ -101,6 +102,7 @@ export const authConfig: AuthConfig = {
}), }),
BoxyHQSAML({ issuer: "https://jackson-demo.boxyhq.com", clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com", clientSecret: "dummy" }), BoxyHQSAML({ issuer: "https://jackson-demo.boxyhq.com", clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com", clientSecret: "dummy" }),
// Cognito({ clientId: process.env.COGNITO_ID, clientSecret: process.env.COGNITO_SECRET, issuer: process.env.COGNITO_ISSUER }), // Cognito({ clientId: process.env.COGNITO_ID, clientSecret: process.env.COGNITO_SECRET, issuer: process.env.COGNITO_ISSUER }),
Descope({ clientId: process.env.DESCOPE_ID, clientSecret: process.env.DESCOPE_SECRET }),
Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }), Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }),
DuendeIDS6({ clientId: "interactive.confidential", clientSecret: "secret", issuer: "https://demo.duendesoftware.com" }), DuendeIDS6({ clientId: "interactive.confidential", clientSecret: "secret", issuer: "https://demo.duendesoftware.com" }),
Facebook({ clientId: process.env.FACEBOOK_ID, clientSecret: process.env.FACEBOOK_SECRET }), Facebook({ clientId: process.env.FACEBOOK_ID, clientSecret: process.env.FACEBOOK_SECRET }),

View File

@@ -6,6 +6,9 @@ AUTH0_ID=
AUTH0_SECRET= AUTH0_SECRET=
AUTH0_ISSUER= AUTH0_ISSUER=
DESCOPE_ID=
DESCOPE_SECRET=
FACEBOOK_ID= FACEBOOK_ID=
FACEBOOK_SECRET= FACEBOOK_SECRET=

View File

@@ -12,5 +12,7 @@ declare namespace NodeJS {
GOOGLE_SECRET: string GOOGLE_SECRET: string
AUTH0_ID: string AUTH0_ID: string
AUTH0_SECRET: string AUTH0_SECRET: string
DESCOPE_ID: string
DESCOPE_SECRET: string
} }
} }

View File

@@ -34,7 +34,7 @@ Most OAuth providers cannot be configured with multiple callback URLs or using a
However, Auth.js **supports Preview deployments**, even **with OAuth providers**: However, Auth.js **supports Preview deployments**, even **with OAuth providers**:
1. Determine a stable deployment URL. Eg.: A deployment whose URL does not change between builds, for example. `auth.yourdomain.com`), 1. Determine a stable deployment URL. Eg.: A deployment whose URL does not change between builds, for example. `auth.yourdomain.com` (using a subdomain is not a requirement, this can simply be the main site's URL too.),
2. Set `AUTH_REDIRECT_PROXY_URL` to that URL, adding the path up until your `[...nextauth]` route. Eg.: (`https://auth.yourdomain.com/api/auth`) 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`) 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`)
@@ -42,6 +42,9 @@ However, Auth.js **supports Preview deployments**, even **with OAuth providers**
To support preview deployments, the `AUTH_SECRET` value needs to be the same for the stable deployment and deployments that will need OAuth support. To support preview deployments, the `AUTH_SECRET` value needs to be the same for the stable deployment and deployments that will need OAuth support.
::: :::
:::note
If you are storing users in a [database](reference/adapters), we recommend using a different OAuth app for development/production so that you don't mix your test and production user base.
:::
<details> <details>
<summary> <summary>

View File

@@ -112,6 +112,7 @@ providers: [
identifier: email, identifier: email,
url, url,
provider: { server, from }, provider: { server, from },
request // for example can be used to get the user agent (`request.headers.get("user-agent")`) to parse and pass on to the user in the email so they can be more confident they originated the request
}) { }) {
/* your function */ /* your function */
}, },

View File

@@ -7,6 +7,7 @@ const icons = [
"/img/providers/apple.svg", "/img/providers/apple.svg",
"/img/providers/auth0.svg", "/img/providers/auth0.svg",
"/img/providers/cognito.svg", "/img/providers/cognito.svg",
"/img/providers/descope.svg",
"/img/providers/battlenet.svg", "/img/providers/battlenet.svg",
"/img/providers/box.svg", "/img/providers/box.svg",
"/img/providers/facebook.svg", "/img/providers/facebook.svg",

50
docs/static/img/providers/descope.svg vendored Normal file
View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.2.1, 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"
width="194.7px" height="215.2px" viewBox="0 0 194.7 215.2" style="enable-background:new 0 0 194.7 215.2;" xml:space="preserve"
>
<style type="text/css">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000004519561486438896460000001266960168497785022_);}
.st2{fill:url(#SVGID_00000049204468076180615810000015113731544435055266_);}
.st3{fill:url(#SVGID_00000116951257355544416270000003794629356563808950_);}
</style>
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="68.3919" y1="222.1531" x2="185.0265" y2="41.0264">
<stop offset="1.481436e-07" style="stop-color:#0083B5"/>
<stop offset="0.4173" style="stop-color:#00FFFF"/>
<stop offset="0.9952" style="stop-color:#6FF12D"/>
</linearGradient>
<path class="st0" d="M129.8,174.7c7.6-1.6,14-4.8,19.2-9.7c7.7-7.3,8.8-17.1,8.8-29.4V80.7c0-12.3-1.1-22.1-8.8-29.4
c-5.2-4.9-11.6-8.1-19.2-9.7V15.4c12.5,1.8,22.9,6.5,31,14.2c10.6,10,19.9,23.5,19.9,40.5v75c0,17-9.3,30.5-19.9,40.5
c-8.1,7.7-18.5,12.4-31,14.2V174.7z"/>
<linearGradient id="SVGID_00000040544740507634666800000017273841385603649669_" gradientUnits="userSpaceOnUse" x1="5.037" y1="181.3564" x2="121.6716" y2="0.2297">
<stop offset="1.481436e-07" style="stop-color:#0083B5"/>
<stop offset="0.4173" style="stop-color:#00FFFF"/>
<stop offset="0.9952" style="stop-color:#6FF12D"/>
</linearGradient>
<path style="fill:url(#SVGID_00000040544740507634666800000017273841385603649669_);" d="M33.9,29.6c8.1-7.7,18.5-12.4,31-14.2
v26.3c-7.6,1.6-14,4.8-19.2,9.7c-7.7,7.3-8.8,17-8.8,29.2v55.1c0,12.3,1.1,22.1,8.8,29.4c5.2,4.9,11.6,8.1,19.2,9.7v25.1
c-12.5-1.8-22.9-6.5-31-14.2c-10.6-10-19.9-23.5-19.9-40.5V69.8C13.9,53,23.2,39.6,33.9,29.6z"/>
<g>
<linearGradient id="SVGID_00000060713993868866928010000000698955780952733088_" gradientUnits="userSpaceOnUse" x1="22.0278" y1="192.2974" x2="138.6624" y2="11.1707">
<stop offset="1.481436e-07" style="stop-color:#0083B5"/>
<stop offset="0.4173" style="stop-color:#00FFFF"/>
<stop offset="0.9952" style="stop-color:#6FF12D"/>
</linearGradient>
<path style="fill:url(#SVGID_00000060713993868866928010000000698955780952733088_);" d="M120.2,87.8l8.5-13.7l-17.8-9.4
l-7.5,14.2c-1.1,2.1-3.1,3.3-5.5,3.3c-2.3,0-4.4-1.2-5.5-3.3L85,64.7L67.3,74l12.3,19.7L120.2,87.8z"/>
<linearGradient id="SVGID_00000115475840050352750520000000840372054167564949_" gradientUnits="userSpaceOnUse" x1="37.9651" y1="202.5601" x2="154.5998" y2="21.4334">
<stop offset="1.481436e-07" style="stop-color:#0083B5"/>
<stop offset="0.4173" style="stop-color:#00FFFF"/>
<stop offset="0.9952" style="stop-color:#6FF12D"/>
</linearGradient>
<path style="fill:url(#SVGID_00000115475840050352750520000000840372054167564949_);" d="M142.4,97.7l-87.8,0.8v17.7l27.5-0.1
l-14.8,23.8l17.7,9.3l7.5-14.2c1.1-2.1,3.1-3.3,5.5-3.3c2.3,0,4.4,1.2,5.5,3.3l7.5,14.2l17.8-9.4l-12-19.3L93.7,116l48.7-0.2V97.7
z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,7 +1,7 @@
{ {
"name": "@auth/dynamodb-adapter", "name": "@auth/dynamodb-adapter",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",
"version": "1.0.0", "version": "1.0.1",
"description": "AWS DynamoDB adapter for next-auth.", "description": "AWS DynamoDB adapter for next-auth.",
"keywords": [ "keywords": [
"next-auth", "next-auth",

View File

@@ -265,9 +265,8 @@ export function DynamoDBAdapter(
const data = await client.update({ const data = await client.update({
TableName, TableName,
Key: { Key: {
// next-auth type is incorrect it should be Partial<AdapterUser> & {id: string} instead of just Partial<AdapterUser> [pk]: `USER#${user.id}`,
[pk]: `USER#${user.id as string}`, [sk]: `USER#${user.id}`,
[sk]: `USER#${user.id as string}`,
}, },
UpdateExpression, UpdateExpression,
ExpressionAttributeNames, ExpressionAttributeNames,

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/mikro-orm-adapter", "name": "@auth/mikro-orm-adapter",
"version": "1.0.0", "version": "1.0.1",
"description": "MikroORM adapter for Auth.js", "description": "MikroORM adapter for Auth.js",
"homepage": "https://authjs.dev", "homepage": "https://authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",

View File

@@ -24,7 +24,7 @@ import type { Adapter } from "@auth/core/adapters"
import { MikroORM, wrap } from "@mikro-orm/core" import { MikroORM, wrap } from "@mikro-orm/core"
import * as defaultEntities from "./lib/entities" import * as defaultEntities from "./lib/entities.js"
export { defaultEntities } export { defaultEntities }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/prisma-adapter", "name": "@auth/prisma-adapter",
"version": "1.0.0", "version": "1.0.1",
"description": "Prisma adapter for Auth.js", "description": "Prisma adapter for Auth.js",
"homepage": "https://authjs.dev/reference/adapter/prisma", "homepage": "https://authjs.dev/reference/adapter/prisma",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",

View File

@@ -21,7 +21,7 @@ import type { Adapter, AdapterAccount } from "@auth/core/adapters"
/** /**
* ## Setup * ## Setup
* *
* Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object: * Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object:
* *
* ```js title="pages/api/auth/[...nextauth].js" * ```js title="pages/api/auth/[...nextauth].js"
* import NextAuth from "next-auth" * import NextAuth from "next-auth"

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/typeorm-adapter", "name": "@auth/typeorm-adapter",
"version": "1.0.0", "version": "1.0.1",
"description": "TypeORM adapter for Auth.js.", "description": "TypeORM adapter for Auth.js.",
"homepage": "https://authjs.dev/reference/adapter/typeorm", "homepage": "https://authjs.dev/reference/adapter/typeorm",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",

View File

@@ -21,8 +21,8 @@ import type {
AdapterSession, AdapterSession,
} from "@auth/core/adapters" } from "@auth/core/adapters"
import { DataSourceOptions, DataSource, EntityManager } from "typeorm" import { DataSourceOptions, DataSource, EntityManager } from "typeorm"
import * as defaultEntities from "./entities" import * as defaultEntities from "./entities.js"
import { parseDataSourceConfig, updateConnectionEntities } from "./utils" import { parseDataSourceConfig, updateConnectionEntities } from "./utils.js"
export const entities = defaultEntities export const entities = defaultEntities

View File

@@ -1,5 +1,5 @@
import type { DataSource, DataSourceOptions } from "typeorm" import type { DataSource, DataSourceOptions } from "typeorm"
import * as defaultEntities from "./entities" import * as defaultEntities from "./entities.js"
/** Ensure configOrString is normalized to an object. */ /** Ensure configOrString is normalized to an object. */
export function parseDataSourceConfig( export function parseDataSourceConfig(

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/core", "name": "@auth/core",
"version": "0.8.4", "version": "0.10.0",
"description": "Authentication for the Web.", "description": "Authentication for the Web.",
"keywords": [ "keywords": [
"authentication", "authentication",

View File

@@ -223,7 +223,7 @@ export interface Adapter {
getUserByAccount?( getUserByAccount?(
providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId"> providerAccountId: Pick<AdapterAccount, "provider" | "providerAccountId">
): Awaitable<AdapterUser | null> ): Awaitable<AdapterUser | null>
updateUser?(user: Partial<AdapterUser>): Awaitable<AdapterUser> updateUser?(user: Partial<AdapterUser> & Pick<AdapterUser, 'id'>): Awaitable<AdapterUser>
/** @todo This method is currently not invoked yet. */ /** @todo This method is currently not invoked yet. */
deleteUser?( deleteUser?(
userId: string userId: string

View File

@@ -1,13 +1,14 @@
import { createHash, randomString } from "../web.js" import { createHash, randomString, toRequest } from "../web.js"
import type { InternalOptions } from "../../types.js" import type { InternalOptions, RequestInternal } from "../../types.js"
/** /**
* Starts an e-mail login flow, by generating a token, * Starts an e-mail login flow, by generating a token,
* and sending it to the user's e-mail (with the help of a DB adapter) * and sending it to the user's e-mail (with the help of a DB adapter)
*/ */
export default async function email( export default async function email(
identifier: string, identifier: string,
options: InternalOptions<"email"> options: InternalOptions<"email">,
request: RequestInternal
): Promise<string> { ): Promise<string> {
const { url, adapter, provider, callbackUrl, theme } = options const { url, adapter, provider, callbackUrl, theme } = options
const token = const token =
@@ -31,6 +32,7 @@ export default async function email(
url: _url, url: _url,
provider, provider,
theme, theme,
request: toRequest(request),
}), }),
// @ts-expect-error -- Verified in `assertConfig`. // @ts-expect-error -- Verified in `assertConfig`.
adapter.createVerificationToken?.({ adapter.createVerificationToken?.({

View File

@@ -137,8 +137,7 @@ export async function AuthInternal<
case "signin": case "signin":
if ((csrfDisabled || options.csrfTokenVerified) && options.provider) { if ((csrfDisabled || options.csrfTokenVerified) && options.provider) {
const signin = await routes.signin( const signin = await routes.signin(
request.query, request,
request.body,
options options
) )
if (signin.cookies) cookies.push(...signin.cookies) if (signin.cookies) cookies.push(...signin.cookies)

View File

@@ -16,10 +16,10 @@ import type {
* For Email, sends an email with a sign in link. * For Email, sends an email with a sign in link.
*/ */
export async function signin( export async function signin(
query: RequestInternal["query"], request: RequestInternal,
body: RequestInternal["body"],
options: InternalOptions<"oauth" | "oidc" | "email"> options: InternalOptions<"oauth" | "oidc" | "email">
): Promise<ResponseInternal> { ): Promise<ResponseInternal> {
const { query, body } = request
const { url, logger, provider } = options const { url, logger, provider } = options
try { try {
if (provider.type === "oauth" || provider.type === "oidc") { if (provider.type === "oauth" || provider.type === "oidc") {
@@ -48,7 +48,7 @@ export async function signin(
if (unauthorizedOrError) return unauthorizedOrError if (unauthorizedOrError) return unauthorizedOrError
const redirect = await emailSignin(email, options) const redirect = await emailSignin(email, options, request)
return { redirect } return { redirect }
} }
return { redirect: `${url}/signin` } return { redirect: `${url}/signin` }

View File

@@ -72,6 +72,17 @@ export async function toInternalRequest(
} }
} }
export function toRequest(request: RequestInternal): Request {
return new Request(request.url, {
headers: request.headers,
method: request.method,
body:
request.method === "POST"
? JSON.stringify(request.body ?? {})
: undefined,
})
}
export function toResponse(res: ResponseInternal): Response { export function toResponse(res: ResponseInternal): Response {
const headers = new Headers(res.headers) const headers = new Headers(res.headers)

View File

@@ -131,6 +131,11 @@ export default function AzureAD<P extends AzureADProfile>(
name: "Azure Active Directory", name: "Azure Active Directory",
type: "oidc", type: "oidc",
wellKnown: `${rest.issuer}}/.well-known/openid-configuration?appid=${options.clientId}`, wellKnown: `${rest.issuer}}/.well-known/openid-configuration?appid=${options.clientId}`,
authorization: {
params: {
scope: 'openid profile email User.Read',
},
},
async profile(profile, tokens) { async profile(profile, tokens) {
// https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples // https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
const response = await fetch( const response = await fetch(

View File

@@ -20,7 +20,7 @@ export interface BoxyHQSAMLProfile extends Record<string, any> {
/** /**
* Add BoxyHQ SAML login to your page. * 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. * BoxyHQ SAML is an open source service that handles the SAML SSO login flow as an OAuth 2.0 flow, abstracting away all the complexities of the SAML protocol. Enable Enterprise single-sign-on in your app with ease.
* *
* 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) * 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)
* *
@@ -32,13 +32,38 @@ export interface BoxyHQSAMLProfile extends Record<string, any> {
* ``` * ```
* *
* #### Configuration * #### Configuration
*
* For OAuth 2.0 Flow:
*```js *```js
* import Auth from "@auth/core" * import Auth from "@auth/core"
* import BoxyHQ from "@auth/core/providers/boxyhq-saml" * import BoxyHQ from "@auth/core/providers/boxyhq-saml"
* *
* const request = new Request(origin) * const request = new Request(origin)
* const response = await Auth(request, { * const response = await Auth(request, {
* providers: [BoxyHQ({ clientId: BOXYHQ_SAML_CLIENT_ID, clientSecret: BOXYHQ_SAML_CLIENT_SECRET. issuer: BOXYHQ_SAML_ISSUER })], * providers: [BoxyHQ({
* authorization: { params: { scope: "" } }, // This is needed for OAuth 2.0 flow, otherwise default to openid
* clientId: BOXYHQ_SAML_CLIENT_ID,
* clientSecret: BOXYHQ_SAML_CLIENT_SECRET,
* issuer: BOXYHQ_SAML_ISSUER
* })],
* })
* ```
* For OIDC Flow:
*
*```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({
* id: "boxyhq-saml-oidc",
* wellKnown: `http://localhost:5225/.well-known/openid-configuration`,
* authorization: { params: { scope: "openid email" } },
* clientId: BOXYHQ_SAML_CLIENT_ID,
* clientSecret: BOXYHQ_SAML_CLIENT_SECRET,
* issuer: BOXYHQ_SAML_ISSUER
* })],
* }) * })
* ``` * ```
* *

View File

@@ -0,0 +1,119 @@
/**
* <div style={{display: "flex", justifyContent: "space-between", alignItems: "center"}}>
* <span style={{fontSize: "1.35rem" }}>
* Built-in sign in with <b>Descope</b> integration.
* </span>
* <a href="https://descope.com" style={{backgroundColor: "#000000", padding: "12px", borderRadius: "100%" }}>
* <img style={{display: "block"}} src="https://authjs.dev/img/providers/descope.svg" width="24"/>
* </a>
* </div>
*
* @module providers/descope
*/
import type { OIDCConfig, OIDCUserConfig } from "./index.js"
/** The returned user profile from Descope when using the profile callback.
* [See Load User](https://docs.descope.com/api/openapi/usermanagement/operation/LoadUser/)
*/
export interface DescopeProfile {
/** The user's unique Descope ID */
sub: string
/** The user's name */
name: string
/** The user's email */
email: string
/** A boolean indicating if the user's email is verified */
email_verified: boolean
/** The user's phone number */
phone_number: string
/** A boolean indicating if the user's phone number is verified */
phone_number_verified: boolean
/** The user's picture */
picture: string
/** The user's custom attributes */
[claim: string]: unknown
}
/**
*
* ### Setup
*
* #### Callback URL
* ```
* https://example.com/api/auth/callback/descope
* ```
*
* #### 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 DescopeProvider from "next-auth/providers/descope";
*
* export default NextAuth({
* providers: [
* DescopeProvider({
* clientId: process.env.DESCOPE_ID,
* clientSecret: process.env.DESCOPE_SECRET,
* }),
* ],
* })
* ```
*
* ### Configuring Descope
*
* Follow these steps:
*
* 1. Log into the [Descope console](https://app.descope.com)
* 2. Follow the [OIDC instructions](https://docs.descope.com/customize/auth/oidc)
*
* Then, create a `.env.local` file in the project root add the following entries:
*
* Get the following from the Descope's console:
* ```
* DESCOPE_ID="<Descope Issuer's last url segment>" # Descope's Issuer can be found in "Authentication Methods > SSO > Identity Provider" (Can also be taken from "Project > Project ID")
* DESCOPE_SECRET="<Descope Access Key>" # Manage > Access Keys
* ```
*
* ### Resources
*
* - [Descope OIDC](https://docs.descope.com/customize/auth/oidc)
* - [Descope Flows](https://docs.descope.com/customize/flows)
*
* ### Notes
*
* The Descope provider comes with a [default configuration](https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/providers/descope.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 Descope provider is based on the [OIDC](https://openid.net/specs/openid-connect-core-1_0.html) spec
* :::
*
* ## 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 Descope(
config: OIDCUserConfig<DescopeProfile>
): OIDCConfig<DescopeProfile> {
return {
id: "descope",
name: "Descope",
type: "oidc",
issuer: `https://api.descope.com/${config.clientId}`,
style: {
logo: "/descope.svg",
logoDark: "/descope.svg",
bg: "#1C1C23",
text: "#ffffff",
bgDark: "#1C1C23",
textDark: "#ffffff",
},
options: config,
}
}

View File

@@ -1,9 +1,17 @@
import { createTransport } from "nodemailer"
import type { CommonProviderOptions } from "./index.js" import type { CommonProviderOptions } from "./index.js"
import type { Options as SMTPTransportOptions } from "nodemailer/lib/smtp-transport"
import type { Awaitable, Theme } from "../types.js" import type { Awaitable, Theme } from "../types.js"
import { Transport, TransportOptions, createTransport } from "nodemailer"
import * as JSONTransport from "nodemailer/lib/json-transport/index.js"
import * as SendmailTransport from "nodemailer/lib/sendmail-transport/index.js"
import * as SESTransport from "nodemailer/lib/ses-transport/index.js"
import * as SMTPTransport from "nodemailer/lib/smtp-transport/index.js"
import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js"
import * as StreamTransport from "nodemailer/lib/stream-transport/index.js"
// TODO: Make use of https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html for the string
type AllTransportOptions = string | SMTPTransport | SMTPTransport.Options | SMTPPool | SMTPPool.Options | SendmailTransport | SendmailTransport.Options | StreamTransport | StreamTransport.Options | JSONTransport | JSONTransport.Options | SESTransport | SESTransport.Options | Transport<any> | TransportOptions
export interface SendVerificationRequestParams { export interface SendVerificationRequestParams {
identifier: string identifier: string
url: string url: string
@@ -11,6 +19,7 @@ export interface SendVerificationRequestParams {
provider: EmailConfig provider: EmailConfig
token: string token: string
theme: Theme theme: Theme
request: Request
} }
/** /**
@@ -26,10 +35,9 @@ export interface SendVerificationRequestParams {
* *
* [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 { export interface EmailUserConfig {
type: "email" server?: AllTransportOptions
// TODO: Make use of https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html type?: "email"
server?: string | SMTPTransportOptions
/** @default `"Auth.js <no-reply@authjs.dev>"` */ /** @default `"Auth.js <no-reply@authjs.dev>"` */
from?: string from?: string
/** /**
@@ -40,7 +48,7 @@ export interface EmailConfig extends CommonProviderOptions {
*/ */
maxAge?: number maxAge?: number
/** [Documentation](https://authjs.dev/guides/providers/email#customizing-emails) */ /** [Documentation](https://authjs.dev/guides/providers/email#customizing-emails) */
sendVerificationRequest: ( sendVerificationRequest?: (
params: SendVerificationRequestParams params: SendVerificationRequestParams
) => Awaitable<void> ) => Awaitable<void>
/** /**
@@ -77,6 +85,31 @@ export interface EmailConfig extends CommonProviderOptions {
normalizeIdentifier?: (identifier: string) => string normalizeIdentifier?: (identifier: string) => string
} }
export interface EmailConfig extends CommonProviderOptions {
// defaults
id: "email"
type: "email"
name: "Email"
server: AllTransportOptions
from: string
maxAge: number
sendVerificationRequest: (
params: SendVerificationRequestParams
) => Awaitable<void>
/**
* This is copied into EmailConfig in parseProviders() don't use elsewhere
*/
options: EmailUserConfig
// user options
// TODO figure out a better way than copying from EmailUserConfig
secret?: string
generateVerificationToken?: () => Awaitable<string>
normalizeIdentifier?: (identifier: string) => string
}
// TODO: Rename to Token provider // TODO: Rename to Token provider
// when started working on https://github.com/nextauthjs/next-auth/discussions/1465 // when started working on https://github.com/nextauthjs/next-auth/discussions/1465
export type EmailProviderType = "email" export type EmailProviderType = "email"
@@ -313,7 +346,7 @@ export type EmailProviderType = "email"
* Always make sure this returns a single e-mail address, even if multiple ones were passed in. * Always make sure this returns a single e-mail address, even if multiple ones were passed in.
* ::: * :::
*/ */
export default function Email(config: EmailConfig): EmailConfig { export default function Email(config: EmailUserConfig): EmailConfig {
return { return {
id: "email", id: "email",
type: "email", type: "email",
@@ -337,7 +370,6 @@ export default function Email(config: EmailConfig): EmailConfig {
throw new Error(`Email (${failed.join(", ")}) could not be sent`) throw new Error(`Email (${failed.join(", ")}) could not be sent`)
} }
}, },
// @ts-expect-error
options: config, options: config,
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@auth/sveltekit", "name": "@auth/sveltekit",
"version": "0.3.3", "version": "0.3.6",
"description": "Authentication for SvelteKit.", "description": "Authentication for SvelteKit.",
"keywords": [ "keywords": [
"authentication", "authentication",
@@ -48,7 +48,7 @@
"@auth/core": "workspace:*" "@auth/core": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {
"svelte": "^3.54.0", "svelte": "^3.54.0 || ^4.0.0",
"@sveltejs/kit": "^1.0.0" "@sveltejs/kit": "^1.0.0"
}, },
"type": "module", "type": "module",

View File

@@ -211,12 +211,13 @@ import type { AuthAction, AuthConfig, Session } from "@auth/core/types"
export async function getSession( export async function getSession(
req: Request, req: Request,
config: AuthConfig config: SvelteKitAuthConfig
): ReturnType<App.Locals["getSession"]> { ): ReturnType<App.Locals["getSession"]> {
config.secret ??= env.AUTH_SECRET config.secret ??= env.AUTH_SECRET
config.trustHost ??= true config.trustHost ??= true
const url = new URL("/api/auth/session", req.url) const prefix = config.prefix ?? "/auth"
const url = new URL(prefix + "/session", req.url)
const request = new Request(url, { headers: req.headers }) const request = new Request(url, { headers: req.headers })
const response = await Auth(request, config) const response = await Auth(request, config)

View File

@@ -173,7 +173,7 @@ export type WithAuthArgs =
/** /**
* Middleware that checks if the user is authenticated/authorized. * Middleware that checks if the user is authenticated/authorized.
* If if they aren't, they will be redirected to the login page. * If they aren't, they will be redirected to the login page.
* Otherwise, continue. * Otherwise, continue.
* *
* @example * @example