Compare commits

..

13 Commits

Author SHA1 Message Date
Thang Vu
f48e0f1e2d Update pnpm-lock.yaml 2022-06-20 14:08:39 +07:00
Thang Vu
2eef2f85d5 Merge branch 'main' into feat/oauth4webapi 2022-06-20 14:04:22 +07:00
Thang Vu
bf31512071 Merge branch 'main' into feat/oauth4webapi 2022-06-20 12:00:44 +07:00
Thang Vu
acc9966285 Update pnpm-lock.yaml 2022-06-10 16:02:27 +07:00
Thang Vu
6dd44000d7 Merge branch 'main' into feat/oauth4webapi 2022-06-10 15:55:26 +07:00
Thang Vu
2267292f5f Improve pkce 2022-04-08 09:13:38 +07:00
Thang Vu
883b36e2b2 check if PKCE supported 2022-04-07 20:40:00 +07:00
Thang Vu
029edb93ee Always use PKCE 2022-04-07 18:46:49 +07:00
Thang Vu
ebcc3280df Some improvement
- handle pkce discovery
- update `validateAuthResponse` to use `expectState`
2022-04-07 15:04:41 +07:00
Thang Vu
70a16e82c3 Throw better error 2022-04-06 17:36:43 +07:00
Thang Vu
1365211a4e Check state only if pkce is not suported 2022-04-06 17:33:54 +07:00
Thang Vu
6df5773220 Revert most breaking changes.
test
2022-04-06 16:31:26 +07:00
Thang Vu
e3e3cf12d1 replace openid-client with oauth4webapi 2022-04-04 15:15:23 +07:00
55 changed files with 5707 additions and 7244 deletions

View File

@@ -69,7 +69,7 @@ jobs:
git config --global user.name "Balázs Orbán"
pnpm release
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN_PKG: ${{ secrets.NPM_TOKEN_PKG }}
NPM_TOKEN_ORG: ${{ secrets.NPM_TOKEN_ORG }}
release-pr:

View File

@@ -1,5 +1,5 @@
// This is an example of how to protect content using server rendering
import { unstable_getServerSession } from "next-auth/next"
import { getServerSession } from "next-auth/next"
import { authOptions } from "./api/auth/[...nextauth]"
import Layout from "../components/layout"
import AccessDenied from "../components/access-denied"
@@ -26,11 +26,7 @@ export default function Page({ content, session }) {
}
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(
context.req,
context.res,
authOptions
)
const session = await getServerSession(context, authOptions)
let content = null
if (session) {

View File

@@ -65,6 +65,7 @@ You **can** skip configuring a database and come back to it later if you want.
For more information about setting up a database, please check out the following links:
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
* Adapters Repo: [nextauthjs/adapters](https://github.com/nextauthjs/adapters)
### 3. Configure Authentication Providers

View File

@@ -68,6 +68,7 @@ You **can** skip configuring a database and come back to it later if you want.
For more information about setting up a database, please check out the following links:
* Docs: [next-auth.js.org/adapters/overview](https://next-auth.js.org/adapters/overview)
* Adapters Repo: [nextauthjs/adapters](https://github.com/nextauthjs/adapters)
### 3. Configure Authentication Providers

View File

@@ -30,7 +30,7 @@
"type": "module",
"dependencies": {
"cookie": "0.4.1",
"next-auth": "^4.5.0"
"next-auth": "^4.3.3"
},
"prettier": {
"semi": false,

View File

@@ -1232,10 +1232,10 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
next-auth@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.5.0.tgz#2df57287fddc705b8971c88c60bad44a89ac6dd1"
integrity sha512-B6gYRIbqtj8nlDsx3y2Ruwp/mvZnItPs7VUULY43QYw+M9xtDPIM9EBZ3ryd/wNYA3MDteBJlzGm/ivseXcmJA==
next-auth@^4.3.3:
version "4.3.3"
resolved "https://registry.yarnpkg.com/next-auth/-/next-auth-4.3.3.tgz#5ff892e73648a0f33c2af0e9d7cafda729f63ae7"
integrity sha512-bUs+oOOPT18Pq/+4v9q4PA/DGoVoAX6jwY7RTfE/akFXwlny+y/mNS6lPSUwpqcHjljqBaq34PQA3+01SdOOPw==
dependencies:
"@babel/runtime" "^7.16.3"
"@panva/hkdf" "^1.0.1"

View File

@@ -1,73 +1,5 @@
# Next.js
## `unstable_getServerSession`
:::warning
This feature is experimental and may be removed or changed in the future.
:::
When calling from server-side i.e. in API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `unstable_getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something.
Otherwise, if you only want to get the session token, see [`getToken`](tutorials/securing-pages-and-api-routes#using-gettoken).
`unstable_getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way:
In `[...nextauth.js]`:
```ts
import { NextAuth } from 'next-auth'
import type { NextAuthOptions } from 'next-auth'
export const authOptions: NextAuthOptions = {
// your configs
}
export default NextAuth(authOptions);
```
In `getServerSideProps`:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
export async function getServerSideProps(context) {
const session = await unstable_getServerSession(context.req, context.res, authOptions)
if (!session) {
return {
redirect: {
destination: '/',
permanent: false,
},
}
}
return {
props: {
session,
},
}
}
```
In API routes:
```js
import { authOptions } from 'pages/api/[...nextauth]'
import { unstable_getServerSession } from "next-auth/next"
export async function handler(req, res) {
const session = await unstable_getServerSession(req, res, authOptions)
if (!session) {
res.status(401).json({ message: "You must be logged in." });
return;
}
return res.json({
message: 'Success',
})
}
```
## Middleware
You can use a Next.js Middleware with NextAuth.js to protect your site.

View File

@@ -30,8 +30,8 @@ import GitHubProvider from "next-auth/providers/github";
...
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
})
]
...

View File

@@ -13,7 +13,7 @@ https://api.slack.com/docs/sign-in-with-slack
https://api.slack.com/apps
:::warning
Slack requires that the redirect URL of your app uses `https`, even for local development. An easy workaround for this is using a service like [`ngrok`](https://ngrok.com) that creates a secure tunnel to your app, using `https`. Remember to set the url as `NEXTAUTH_URL` as well.
Slack requires you that the redirect URL of your app uses `https`, even for local development. An easy workaround for this is using a service like [`ngrok`](https://ngrok.com) that creates a secure tunnel to your app, using `https`. Remember to set the url as `NEXTAUTH_URL` as well.
:::
![](https://i.imgur.com/ydYKTLD.png)

View File

@@ -33,10 +33,6 @@ In development, we generate a `secret` based on your configuration for convenien
Twitter OAuth 2.0 is currently in beta as certain changes might still be necessary. This is not covered by semver. See the docs https://next-auth.js.org/providers/twitter#oauth-2
#### EXPERIMENTAL_API
Some APIs are still experimental; they may be changed or removed in the future. Use at your own risk.
## Adapter
### ADAPTER_TYPEORM_UPDATING_ENTITIES

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<!-- <p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter" alt="@next-auth/prisma-adapter Version" />
</p> -->
@@ -150,7 +150,7 @@ type User
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,9 +3,9 @@
"version": "1.0.3",
"description": "Dgraph adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "Arnaud Derbey <arnaud@derbey.dev>",
"contributors": [],

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/dynamodb-adapter/latest" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/dynamodb-adapter" alt="@next-auth/dynamodb-adapter Version" />
</p>
@@ -96,7 +96,7 @@ Here is a schema of the table :
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

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

View File

@@ -7,7 +7,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/fauna-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/faunadb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/fauna-adapter/next" alt="@next-auth/fauna-adapter Version" /></a>
</p>
@@ -53,7 +53,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3",
"description": "Fauna Adapter for NextAuth",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -7,7 +7,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Build Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Build Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/firebase-adapter/latest" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/firebase-adapter" alt="@next-auth/firebase-adapter Version" />
</p>
@@ -83,7 +83,7 @@ See [firebase.google.com/docs/web/setup](https://firebase.google.com/docs/web/se
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,9 +3,9 @@
"version": "0.1.3",
"description": "Firebase adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "Ron Houben <ron.houben85@gmail.com>",
"contributors": [

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mikro-orm-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/mikro-orm-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mikro-orm-adapter/next" alt="@next-auth/mikro-orm-adapter Version" /></a>
</p>
@@ -49,7 +49,7 @@ This is the MikroORM Adapter for [`next-auth`](https://next-auth.js.org). This p
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "2.0.1",
"description": "MikroORM adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/mongodb-adapter" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/mongodb-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/mongodb-adapter" alt="@next-auth/mongodb-adapter Version" /></a>
</p>
@@ -79,7 +79,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3",
"description": "mongoDB adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Canary CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Canary CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/neo4j-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/neo4j-adapter" alt="@next-auth/neo4j-adapter Version" />
</p>
@@ -50,7 +50,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please first read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/canary/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please first read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/canary/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3",
"description": "neo4j adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/pouchdb-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/pouchdb-adapter" alt="@next-auth/pouchdb-adapter Version" />
</p>
@@ -71,7 +71,7 @@ For more details, please see https://pouchdb.com/api.html#sync
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "0.1.3",
"description": "PouchDB adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/bundlephobia/minzip/@next-auth/prisma-adapter/next" alt="Bundle Size"/></a>
<a href="https://www.npmjs.com/package/@next-auth/prisma-adapter" target="_blank"><img src="https://img.shields.io/npm/v/@next-auth/prisma-adapter/next" alt="@next-auth/prisma-adapter Version" /></a>
</p>
@@ -48,7 +48,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,7 +3,7 @@
"version": "1.0.3",
"description": "Prisma adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
},

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/sequelize-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/sequelize-adapter" alt="@next-auth/sequelize-adapter Version" />
</p>
@@ -89,7 +89,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,9 +3,9 @@
"version": "1.0.4",
"description": "Sequelize adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "github.com/luke-j",
"main": "dist/index.js",

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="Canary CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="Canary CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/typeorm-legacy-adapter/canary" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/typeorm-legacy-adapter" alt="@next-auth/typeorm-legacy-adapter Version" />
</p>

View File

@@ -3,9 +3,9 @@
"version": "1.0.3",
"description": "TypeORM (legacy) adapter for next-auth.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "Iain Collins",
"contributors": [

View File

@@ -6,7 +6,7 @@
Open Source. Full Stack. Own Your Data.
</p>
<p align="center" style="align: center;">
<img src="https://github.com/nextauthjs/next-auth/actions/workflows/release.yml/badge.svg?branch=main" alt="CI Test" />
<img src="https://github.com/nextauthjs/adapters/actions/workflows/release.yml/badge.svg" alt="CI Test" />
<img src="https://img.shields.io/bundlephobia/minzip/@next-auth/upstash-adapter" alt="Bundle Size"/>
<img src="https://img.shields.io/npm/v/@next-auth/upstash-adapter" alt="@next-auth/upstash-adapter Version" />
</p>
@@ -80,7 +80,7 @@ export default NextAuth({
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/next-auth/blob/main/CONTRIBUTING.md).
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
## License

View File

@@ -3,9 +3,9 @@
"version": "3.0.0",
"description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "github.com/kay-is",
"main": "dist/index.js",

View File

@@ -25,6 +25,7 @@ module.exports = (api) => {
ignore: [
"../src/**/__tests__/**",
"../src/adapters.ts",
"../src/core/types.ts",
"../src/providers/oauth-types.ts",
],
comments: false,

View File

@@ -1,6 +1,6 @@
{
"name": "next-auth",
"version": "4.6.1",
"version": "4.5.0",
"description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git",
@@ -62,17 +62,16 @@
"index.js",
"adapters.d.ts",
"middleware.d.ts",
"middleware.js",
"utils"
"middleware.js"
],
"license": "ISC",
"dependencies": {
"@babel/runtime": "^7.16.3",
"@panva/hkdf": "^1.0.1",
"@panva/oauth4webapi": "^0.0.10",
"cookie": "^0.4.1",
"jose": "^4.3.7",
"oauth": "^0.9.15",
"openid-client": "^5.1.0",
"preact": "^10.6.3",
"preact-render-to-string": "^5.1.19",
"uuid": "^8.3.2"

View File

@@ -52,7 +52,7 @@ export interface VerificationToken {
* - `deleteUser`
* - `unlinkAccount`
*
* [Adapters Overview](https://next-auth.js.org/adapters/overview) |
* [Community adapters](https://github.com/nextauthjs/adapters) |
* [Create a custom adapter](https://next-auth.js.org/tutorials/creating-a-database-adapter)
*/
export interface Adapter {

View File

@@ -44,7 +44,7 @@ export function assertConfig(
): ConfigError | WarningCode | undefined {
const { options, req } = params
// req.query isn't defined when asserting `unstable_getServerSession` for example
// req.query isn't defined when asserting `getServerSession` for example
if (!req.query?.nextauth && !req.action) {
return new MissingAPIRoute(
"Cannot find [...nextauth].{js,ts} in `/pages/api/auth`. Make sure the filename is written correctly."

View File

@@ -120,7 +120,7 @@ export class SessionStore {
constructor(
option: CookieOption,
req: {
cookies?: Record<string, string> | { get: (key: string) => string }
cookies?: Record<string, string>
headers?: Headers | IncomingHttpHeaders | Record<string, string>
},
logger: LoggerInstance | Console
@@ -132,10 +132,7 @@ export class SessionStore {
for (const name in req.cookies) {
if (name.startsWith(option.name)) {
this.#chunks[name] =
typeof req.cookies.get === "function"
? req.cookies.get(name)
: req.cookies[name]
this.#chunks[name] = req.cookies[name]
}
}
}

View File

@@ -0,0 +1,32 @@
import { discoveryRequest, processDiscoveryResponse } from "@panva/oauth4webapi"
import type { AuthorizationServer } from "@panva/oauth4webapi"
import type { InternalProvider } from "src/lib/types"
export default async function getAuthorizationServer(
provider: InternalProvider<"oauth">
): Promise<AuthorizationServer> {
if (provider.idToken) {
const issuer = new URL(provider.issuer as string)
return await discoveryRequest(issuer).then(
async (response) => await processDiscoveryResponse(issuer, response)
)
} else {
return {
issuer: provider.issuer as string,
authorization_endpoint:
typeof provider.authorization === "string"
? provider.authorization
: provider.authorization?.url,
token_endpoint:
typeof provider.token === "string"
? provider.token
: provider.token?.url,
userinfo_endpoint:
typeof provider.userinfo === "string"
? provider.userinfo
: provider.userinfo?.url,
jwks_uri: provider.jwks_uri,
}
}
}

View File

@@ -1,7 +1,7 @@
import { openidClient } from "./client"
import { oAuth1Client } from "./client-legacy"
import { createState } from "./state-handler"
import { createPKCE } from "./pkce-handler"
import getAuthorizationServer from "./authorization-server"
import type { AuthorizationParameters } from "openid-client"
import type { InternalOptions } from "../../types"
@@ -50,28 +50,53 @@ export default async function getAuthorizationUrl(params: {
return { redirect: url }
}
const client = await openidClient(options)
const authorizationServer = await getAuthorizationServer(provider)
if (!authorizationServer.authorization_endpoint) throw new Error()
const authorizationUrl = new URL(authorizationServer.authorization_endpoint)
for (const [key, value] of Object.entries(params)) {
authorizationUrl.searchParams.set(key, value as string)
}
authorizationUrl.searchParams.set("client_id", provider.clientId as string)
authorizationUrl.searchParams.set("redirect_uri", provider.callbackUrl)
if (typeof provider.authorization !== "string" && provider.authorization) {
const { params: authorizationEndpointParams } = provider.authorization
if (typeof authorizationEndpointParams?.response_type === "string") {
authorizationUrl.searchParams.set(
"response_type",
authorizationEndpointParams.response_type
)
}
if (typeof authorizationEndpointParams?.scope === "string") {
authorizationUrl.searchParams.set(
"scope",
authorizationEndpointParams.scope
)
}
}
const authorizationParams: AuthorizationParameters = params
const cookies: Cookie[] = []
const pkce = await createPKCE(options, authorizationServer)
authorizationUrl.searchParams.set("code_challenge", pkce.code_challenge)
authorizationUrl.searchParams.set(
"code_challenge_method",
pkce.code_challenge_method
)
cookies.push(pkce.cookie)
const state = await createState(options)
if (state) {
authorizationParams.state = state.value
if (!pkce.isSupported && state) {
authorizationUrl.searchParams.set("state", state.value)
cookies.push(state.cookie)
}
const pkce = await createPKCE(options)
if (pkce) {
authorizationParams.code_challenge = pkce.code_challenge
authorizationParams.code_challenge_method = pkce.code_challenge_method
cookies.push(pkce.cookie)
}
const url = client.authorizationUrl(authorizationParams)
logger.debug("GET_AUTHORIZATION_URL", { url, cookies })
return { redirect: url, cookies }
logger.debug("GET_AUTHORIZATION_URL", { authorizationUrl, cookies })
return { redirect: authorizationUrl.href, cookies }
} catch (error) {
logger.error("GET_AUTHORIZATION_URL_ERROR", error as Error)
throw error

View File

@@ -1,16 +1,31 @@
import { TokenSet } from "openid-client"
import { openidClient } from "./client"
import { oAuth1Client } from "./client-legacy"
import { useState } from "./state-handler"
import { usePKCECodeVerifier } from "./pkce-handler"
import { OAuthCallbackError } from "../../errors"
import {
authorizationCodeGrantRequest,
expectNoState,
getValidatedIdTokenClaims,
isOAuth2Error,
processAuthorizationCodeOAuth2Response,
processAuthorizationCodeOpenIDResponse,
processUserInfoResponse,
userInfoRequest,
validateAuthResponse,
} from "@panva/oauth4webapi"
import getAuthorizationServer from "./authorization-server"
import type { CallbackParamsType } from "openid-client"
import type { Account, LoggerInstance, Profile } from "../../.."
import type { OAuthChecks, OAuthConfig } from "../../../providers"
import type { InternalOptions } from "../../types"
import type { RequestInternal, OutgoingResponse } from "../.."
import type { Cookie } from "../cookie"
import type {
OAuth2Error,
OAuth2TokenEndpointResponse,
OpenIDTokenEndpointResponse,
} from "@panva/oauth4webapi"
export default async function oAuthCallback(params: {
options: InternalOptions<"oauth">
@@ -19,7 +34,7 @@ export default async function oAuthCallback(params: {
method: Required<RequestInternal>["method"]
cookies: RequestInternal["cookies"]
}): Promise<GetProfileResult & { cookies?: OutgoingResponse["cookies"] }> {
const { options, query, body, method, cookies } = params
const { options, query, body, cookies } = params
const { logger, provider } = options
const errorMessage = body?.error ?? query?.error
@@ -65,81 +80,111 @@ export default async function oAuthCallback(params: {
}
try {
const client = await openidClient(options)
const client = openidClient(provider)
const authorizationServer = await getAuthorizationServer(provider)
let tokens: TokenSet
let tokens:
| OpenIDTokenEndpointResponse
| OAuth2TokenEndpointResponse
| OAuth2Error
const checks: OAuthChecks = {}
let expectedState: string | typeof expectNoState = expectNoState
const resCookies: Cookie[] = []
const authParams = new URLSearchParams(query)
const codeVerifier = cookies?.[options.cookies.pkceCodeVerifier.name]
const pkce = await usePKCECodeVerifier(
codeVerifier,
options,
authorizationServer
)
resCookies.push(pkce.cookie)
const state = await useState(cookies?.[options.cookies.state.name], options)
if (state) {
checks.state = state.value
if (!pkce.isSupported && state) {
resCookies.push(state.cookie)
expectedState = state.value
authParams.append("state", state.value)
}
const codeVerifier = cookies?.[options.cookies.pkceCodeVerifier.name]
const pkce = await usePKCECodeVerifier(codeVerifier, options)
if (pkce) {
checks.code_verifier = pkce.codeVerifier
resCookies.push(pkce.cookie)
const callbackParameters = validateAuthResponse(
authorizationServer,
client,
authParams,
expectedState
)
if (isOAuth2Error(callbackParameters)) {
throw new OAuthCallbackError(callbackParameters.error)
}
const params: CallbackParamsType = {
...client.callbackParams({
url: `http://n?${new URLSearchParams(query)}`,
// TODO: Ask to allow object to be passed upstream:
// https://github.com/panva/node-openid-client/blob/3ae206dfc78c02134aa87a07f693052c637cab84/types/index.d.ts#L439
// @ts-expect-error
body,
method,
}),
// @ts-expect-error
...provider.token?.params,
}
const response = await authorizationCodeGrantRequest(
authorizationServer,
client,
callbackParameters,
provider.callbackUrl,
pkce.codeVerifier
)
// @ts-expect-error
if (provider.token?.request) {
// @ts-expect-error
if (typeof provider.token !== "string" && provider.token?.request) {
const params = {
...callbackParameters,
...provider.token?.params,
}
const checks = new URLSearchParams()
if (state) checks.append("state", state.value)
checks.append("code_verifier", pkce.codeVerifier)
const response = await provider.token.request({
provider,
params,
checks,
client,
})
tokens = new TokenSet(response.tokens)
tokens = response.tokens
} else if (provider.idToken) {
tokens = await client.callback(provider.callbackUrl, params, checks)
tokens = await processAuthorizationCodeOpenIDResponse(
authorizationServer,
client,
response
)
} else {
tokens = await client.oauthCallback(provider.callbackUrl, params, checks)
tokens = await processAuthorizationCodeOAuth2Response(
authorizationServer,
client,
response
)
}
// REVIEW: How can scope be returned as an array?
if (Array.isArray(tokens.scope)) {
tokens.scope = tokens.scope.join(" ")
if (isOAuth2Error(tokens)) {
throw new OAuthCallbackError(tokens.error)
}
let profile: Profile
// @ts-expect-error
if (provider.userinfo?.request) {
// @ts-expect-error
let profile: Profile | Response
if (typeof provider.userinfo !== "string" && provider.userinfo?.request) {
profile = await provider.userinfo.request({
provider,
tokens,
client,
})
} else if (provider.idToken) {
profile = tokens.claims()
const idToken = getValidatedIdTokenClaims(tokens)
profile = await processUserInfoResponse(
authorizationServer,
client,
idToken?.sub as string,
response
)
} else {
profile = await client.userinfo(tokens, {
// @ts-expect-error
params: provider.userinfo?.params,
})
profile = await userInfoRequest(
authorizationServer,
client,
tokens.access_token
)
}
const profileResult = await getProfile({
profile,
profile: profile as Profile,
provider,
tokens,
logger,
@@ -156,7 +201,7 @@ export default async function oAuthCallback(params: {
export interface GetProfileParams {
profile: Profile
tokens: TokenSet
tokens: OpenIDTokenEndpointResponse | OAuth2TokenEndpointResponse
provider: OAuthConfig<any>
logger: LoggerInstance
}

View File

@@ -1,14 +1,20 @@
import { InternalProvider } from "src/lib/types"
import type { Client as WebApiClient } from "@panva/oauth4webapi"
import { Issuer, custom } from "openid-client"
import type { Client } from "openid-client"
import type { InternalOptions } from "../../types"
/**
* NOTE: We can add auto discovery of the provider's endpoint
* that requires only one endpoint to be specified by the user.
* Check out `Issuer.discover`
*
* Client supporting OAuth 2.x and OIDC
*/
export function webApiClient(provider: InternalProvider<"oauth">): WebApiClient {
return {
client_id: provider.clientId as string,
client_secret: provider.clientSecret as string,
token_endpoint_auth_method: "client_secret_basic",
...provider.client,
}
}
export async function openidClient(
options: InternalOptions<"oauth">
): Promise<Client> {
@@ -31,21 +37,4 @@ export async function openidClient(
userinfo_endpoint: provider.userinfo?.url ?? provider.userinfo,
})
}
const client = new issuer.Client(
{
client_id: provider.clientId as string,
client_secret: provider.clientSecret as string,
redirect_uris: [provider.callbackUrl],
...provider.client,
},
provider.jwks
)
// allow a 10 second skew
// See https://github.com/nextauthjs/next-auth/issues/3032
// and https://github.com/nextauthjs/next-auth/issues/3067
client[custom.clock_tolerance] = 10
return client
}

View File

@@ -0,0 +1,9 @@
import { generateRandomCodeVerifier } from "@panva/oauth4webapi"
/**
* Generate random `state` value encoded as base64url. This method returns oauth4webapi's `generateRandomCodeVerifier` for convenience.
* @see {@link https://github.com/panva/oauth4webapi/blob/main/docs/functions/generateRandomCodeVerifier.md generateRandomCodeVerifier.}
*/
export function generateRandomState() {
return generateRandomCodeVerifier()
}

View File

@@ -1,30 +1,43 @@
import * as jwt from "../../../jwt"
import {
generateRandomCodeVerifier,
calculatePKCECodeChallenge,
} from "@panva/oauth4webapi"
import { generators } from "openid-client"
import type { InternalOptions } from "../../types"
import type { Cookie } from "../cookie"
import type { AuthorizationServer } from "@panva/oauth4webapi"
const PKCE_CODE_CHALLENGE_METHOD = "S256"
const PKCE_MAX_AGE = 60 * 15 // 15 minutes in seconds
/**
* Check if PKCE is supported by the authorization server.
* @see {@link https://datatracker.ietf.org/doc/html/rfc8414#section-2 code_challenge_methods_supported}
* @param as The authorization server. @see {@link https://github.com/panva/oauth4webapi/blob/main/docs/interfaces/AuthorizationServer.md AuthorizationServer}
*/
function isPKCESupported(as: AuthorizationServer) {
return !!as.code_challenge_methods_supported?.includes(
PKCE_CODE_CHALLENGE_METHOD
)
}
/**
* Returns `code_challenge` and `code_challenge_method`
* and saves them in a cookie.
*/
export async function createPKCE(options: InternalOptions<"oauth">): Promise<
| undefined
| {
code_challenge: string
code_challenge_method: "S256"
cookie: Cookie
}
> {
const { cookies, logger, provider } = options
if (!provider.checks?.includes("pkce")) {
// Provider does not support PKCE, return nothing.
return
}
const code_verifier = generators.codeVerifier()
const code_challenge = generators.codeChallenge(code_verifier)
export async function createPKCE(
options: InternalOptions<"oauth">,
as: AuthorizationServer
): Promise<{
code_challenge: string
code_challenge_method: "S256"
cookie: Cookie
isSupported: boolean
}> {
const { cookies, logger } = options
const code_verifier = generateRandomCodeVerifier()
const code_challenge = await calculatePKCECodeChallenge(code_verifier)
const expires = new Date()
expires.setTime(expires.getTime() + PKCE_MAX_AGE * 1000)
@@ -51,34 +64,37 @@ export async function createPKCE(options: InternalOptions<"oauth">): Promise<
value: encryptedCodeVerifier,
options: { ...cookies.pkceCodeVerifier.options, expires },
},
isSupported: isPKCESupported(as),
}
}
/**
* Returns code_verifier if provider uses PKCE,
* Returns `code_verifier`,
* and clears the container cookie afterwards.
*/
export async function usePKCECodeVerifier(
codeVerifier: string | undefined,
options: InternalOptions<"oauth">
): Promise<{ codeVerifier: string; cookie: Cookie } | undefined> {
const { cookies, provider } = options
options: InternalOptions<"oauth">,
as: AuthorizationServer
): Promise<{ codeVerifier: string; cookie: Cookie; isSupported: boolean }> {
if (codeVerifier === undefined) throw new Error("Invalid code verifier")
if (!provider?.checks?.includes("pkce") || !codeVerifier) {
return
}
const { cookies } = options
const pkce = (await jwt.decode({
const pkce = await jwt.decode({
...options.jwt,
token: codeVerifier,
})) as any
})
if (pkce === null) throw new Error("Invalid code verifier")
return {
codeVerifier: pkce?.code_verifier ?? undefined,
codeVerifier: pkce.code_verifier as string,
cookie: {
name: cookies.pkceCodeVerifier.name,
value: "",
options: { ...cookies.pkceCodeVerifier.options, maxAge: 0 },
},
isSupported: isPKCESupported(as),
}
}

View File

@@ -2,6 +2,7 @@ import { generators } from "openid-client"
import type { InternalOptions } from "../../types"
import type { Cookie } from "../cookie"
import { generateRandomState } from "./helper"
const STATE_MAX_AGE = 60 * 15 // 15 minutes in seconds
@@ -16,7 +17,7 @@ export async function createState(
return
}
const state = generators.state()
const state = generateRandomState()
const encodedState = await jwt.encode({
...jwt,

View File

@@ -11,10 +11,11 @@ import type { TokenSetParameters } from "openid-client"
import type { JWT, JWTOptions } from "../jwt"
import type { LoggerInstance } from "../utils/logger"
import type { CookieSerializeOptions } from "cookie"
import type { TokenEndpointResponse } from "@panva/oauth4webapi"
import type { NextApiRequest, NextApiResponse } from "next"
import type { InternalUrl } from "../utils/parse-url"
import { InternalUrl } from "../utils/parse-url"
export type Awaitable<T> = T | PromiseLike<T>
@@ -117,7 +118,7 @@ export interface NextAuthOptions {
* * **Required**: *No*
*
* [Documentation](https://next-auth.js.org/configuration/options#adapter) |
* [Adapters Overview](https://next-auth.js.org/adapters/overview)
* [Community adapters](https://github.com/nextauthjs/adapters)
*/
adapter?: Adapter
/**
@@ -224,7 +225,7 @@ export interface Theme {
* Some of them are available with different casing,
* but they refer to the same value.
*/
export type TokenSet = TokenSetParameters
export type TokenSet = TokenEndpointResponse
/**
* Usually contains information about the provider being used

View File

@@ -67,7 +67,7 @@ function NextAuth(
options: NextAuthOptions
): any
/** The main entry point to next-auth */
/** Tha main entry point to next-auth */
function NextAuth(
...args:
| [NextAuthOptions]
@@ -83,33 +83,26 @@ function NextAuth(
export default NextAuth
export async function unstable_getServerSession(
...args:
| [GetServerSidePropsContext['req'], GetServerSidePropsContext['res'], NextAuthOptions]
| [NextApiRequest, NextApiResponse, NextAuthOptions]
export async function getServerSession(
context:
| GetServerSidePropsContext
| { req: NextApiRequest; res: NextApiResponse },
options: NextAuthOptions
): Promise<Session | null> {
console.warn(
"[next-auth][warn][EXPERIMENTAL_API]",
"\n`unstable_getServerSession` is experimental and may be removed or changed in the future, as the name suggested.",
`\nhttps://next-auth.js.org/configuration/nextjs#unstable_getServerSession}`,
`\nhttps://next-auth.js.org/warnings#EXPERIMENTAL_API`
)
const [req, res, options] = args;
const session = await NextAuthHandler<Session | {}>({
options,
req: {
host: detectHost(req.headers["x-forwarded-host"]),
host: detectHost(context.req.headers["x-forwarded-host"]),
action: "session",
method: "GET",
cookies: req.cookies,
headers: req.headers,
cookies: context.req.cookies,
headers: context.req.headers,
},
})
const { body, cookies } = session
cookies?.forEach((cookie) => setCookie(res, cookie))
cookies?.forEach((cookie) => setCookie(context.res, cookie))
if (body && Object.keys(body).length) return body as Session
return null

View File

@@ -1,3 +1,4 @@
import { AuthorizationServer, userInfoRequest } from "@panva/oauth4webapi"
import type { OAuthConfig, OAuthUserConfig } from "."
interface FacebookPictureData {
@@ -26,11 +27,17 @@ export default function Facebook<P extends FacebookProfile>(
// https://developers.facebook.com/docs/graph-api/reference/user/#fields
params: { fields: "id,name,email,picture" },
async request({ tokens, client, provider }) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return await client.userinfo(tokens.access_token!, {
// @ts-expect-error
params: provider.userinfo?.params,
// @ts-expect-error
const userinfo_endpoint = new URL(provider.userinfo?.url)
// @ts-expect-error
Object.entries(provider.userinfo?.params).forEach(([key, value]) => {
userinfo_endpoint.searchParams.append(key, value as string)
})
const as: AuthorizationServer = {
issuer: options.issuer as string,
userinfo_endpoint: userinfo_endpoint.href,
}
return await userInfoRequest(as, client, tokens.access_token)
},
},
profile(profile: P) {

View File

@@ -1,33 +1,20 @@
import type { CommonProviderOptions } from "../providers"
import type { Profile, TokenSet, User, Awaitable } from ".."
import type {
AuthorizationParameters,
CallbackParamsType,
Issuer,
ClientMetadata,
IssuerMetadata,
OAuthCallbackChecks,
OpenIDCallbackChecks,
HttpOptions,
} from "openid-client"
import type { JWK } from "jose"
type Client = InstanceType<Issuer["Client"]>
import type { AuthorizationServer, Client } from "@panva/oauth4webapi"
export type { OAuthProviderType } from "./oauth-types"
type ChecksType = "pkce" | "state" | "none"
export type OAuthChecks = OpenIDCallbackChecks | OAuthCallbackChecks
type PartialIssuer = Partial<Pick<IssuerMetadata, "jwks_endpoint" | "issuer">>
type PartialIssuer = Partial<Pick<AuthorizationServer, "jwks_uri" | "issuer">>
type UrlParams = Record<string, unknown>
type EndpointRequest<C, R, P> = (
context: C & {
/** `openid-client` Client */
/** `oauth4webapi` Client */
client: Client
/** Provider is passed for convenience, ans also contains the `callbackUrl`. */
provider: OAuthConfig<P> & {
@@ -61,8 +48,7 @@ export type EndpointHandler<
R = any
> = AdvancedEndpointHandler<P, C, R>
export type AuthorizationEndpointHandler =
EndpointHandler<AuthorizationParameters>
export type AuthorizationEndpointHandler = EndpointHandler<UrlParams>
export type TokenEndpointHandler = EndpointHandler<
UrlParams,
@@ -71,12 +57,12 @@ export type TokenEndpointHandler = EndpointHandler<
* Parameters extracted from the request to the `/api/auth/callback/:providerId` endpoint.
* Contains params like `state`.
*/
params: CallbackParamsType
params: URLSearchParams
/**
* When using this custom flow, make sure to do all the necessary security checks.
* Thist object contains parameters you have to match against the request to make sure it is valid.
* This object contains parameters you have to match against the request to make sure it is valid.
*/
checks: OAuthChecks
checks: URLSearchParams
},
{
tokens: TokenSet
@@ -86,7 +72,7 @@ export type TokenEndpointHandler = EndpointHandler<
export type UserinfoEndpointHandler = EndpointHandler<
UrlParams,
{ tokens: TokenSet },
Profile
Profile | Response
>
export interface OAuthConfig<P> extends CommonProviderOptions, PartialIssuer {
@@ -112,7 +98,7 @@ export interface OAuthConfig<P> extends CommonProviderOptions, PartialIssuer {
version?: string
profile?: (profile: P, tokens: TokenSet) => Awaitable<User & { id: string }>
checks?: ChecksType | ChecksType[]
client?: Partial<ClientMetadata>
client?: Partial<Client>
jwks?: { keys: JWK[] }
clientId?: string
clientSecret?: string
@@ -128,11 +114,6 @@ export interface OAuthConfig<P> extends CommonProviderOptions, PartialIssuer {
idToken?: boolean
// TODO: only allow for BattleNet
region?: string
// TODO: only allow for some
issuer?: string
/** Read more at: https://github.com/panva/node-openid-client/tree/main/docs#customizing-http-requests */
httpOptions?: HttpOptions
/**
* The options provided by the user.
* We will perform a deep-merge of these values

View File

@@ -1,4 +1,10 @@
import type { OAuthConfig, OAuthUserConfig } from "."
import {
authorizationCodeGrantRequest,
AuthorizationServer,
isOAuth2Error,
processAuthorizationCodeOAuth2Response,
} from "@panva/oauth4webapi"
export interface TwitterLegacyProfile {
id: number
@@ -183,13 +189,33 @@ export default function Twitter<
url: "https://api.twitter.com/2/oauth2/token",
// TODO: Remove this
async request({ client, params, checks, provider }) {
const response = await client.oauthCallback(
provider.callbackUrl,
const as: AuthorizationServer = {
issuer: options.issuer as string,
// @ts-expect-error
token_endpoint: provider.token?.url,
}
const additionalParameters = new URLSearchParams()
additionalParameters.append("client_id", options.clientId)
const response = await authorizationCodeGrantRequest(
as,
client,
params,
checks,
{ exchangeBody: { client_id: options.clientId } }
provider.callbackUrl,
checks.get("code_verifier") as string,
{
additionalParameters,
}
)
return { tokens: response }
const tokens = await processAuthorizationCodeOAuth2Response(
as,
client,
response
)
if (isOAuth2Error(tokens)) {
throw new Error()
}
return { tokens }
},
},
userinfo: {

View File

@@ -175,7 +175,7 @@ export async function getProviders() {
export async function signIn<
P extends RedirectableProviderType | undefined = undefined
>(
provider?: LiteralUnion<P extends RedirectableProviderType ? P | BuiltInProviderType : BuiltInProviderType>,
provider?: LiteralUnion<BuiltInProviderType>,
options?: SignInOptions,
authorizationParams?: SignInAuthorizationParams
): Promise<

View File

@@ -13,22 +13,6 @@ it("Show error page if secret is not defined", async () => {
expect(log.error).toBeCalledWith("NO_SECRET", expect.anything())
})
it("Should show configuration error page on invalid `callbackUrl`", async () => {
const { res, log } = await handler(
{ providers: [] },
{ prod: true, params: { callbackUrl: "invalid-callback" } }
)
expect(res.status).toBe(500)
expect(res.html).toMatch(/there is a problem with the server configuration./i)
expect(res.html).toMatch(/check the server logs for more information./i)
expect(log.error).toBeCalledWith(
"INVALID_CALLBACK_URL_ERROR",
expect.anything()
)
})
it("Allow relative `callbackUrl`", async () => {
const { res, log } = await handler(
{ providers: [] },

View File

@@ -14,8 +14,7 @@
"stripInternal": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"outDir": ".",
"outDir": "."
},
"exclude": ["./*.js", "./*.d.ts", "config", "**/__tests__", "tests"]
}

12276
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff