Skip to content

Commit

Permalink
Merge pull request #1 from nextauthjs/feat/oauth4webapi-balazs
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsorban44 authored Dec 8, 2022
2 parents 57faccc + 187d38b commit 59d6385
Show file tree
Hide file tree
Showing 77 changed files with 1,636 additions and 674 deletions.
2 changes: 2 additions & 0 deletions .github/actions/issue-validator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
!dist
!package-lock.json
7 changes: 7 additions & 0 deletions .github/actions/issue-validator/index.mjs

Large diffs are not rendered by default.

652 changes: 652 additions & 0 deletions .github/actions/issue-validator/licenses.txt

Large diffs are not rendered by default.

445 changes: 445 additions & 0 deletions .github/actions/issue-validator/package-lock.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions .github/actions/issue-validator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"private": true,
"exports": "./index.mjs",
"scripts": {
"build": "ncc -m -o . build src/index.mjs --license licenses.txt"
},
"devDependencies": {
"@vercel/ncc": "0.34.0"
},
"dependencies": {
"@actions/core": "1.10.0",
"@actions/github": "5.1.1"
}
}
38 changes: 38 additions & 0 deletions .github/actions/issue-validator/repro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
We cannot recreate the issue with the provided information. **Please add a reproduction in order for us to be able to investigate.**

### **Why was this issue marked with the `incomplete` label?**

To be able to investigate, we need access to a reproduction to identify what triggered the issue. We prefer a link to a public GitHub repository ([template](https://github.com/nextauthjs/next-auth-example)), but you can also use a tool like [CodeSandbox](https://codesandbox.io/s/github/nextauthjs/next-auth-example/tree/main) or [StackBlitz](https://stackblitz.com/fork/github/nextauthjs/next-auth-example).

To make sure the issue is resolved as quickly as possible, please make sure that the reproduction is as **minimal** as possible. This means that you should **remove unnecessary code, files, and dependencies** that do not contribute to the issue.

Please test your reproduction against the latest version of NextAuth.js (`next-auth@latest`) to make sure your issue has not already been fixed.

### **I added a link, why was it still marked?**

Ensure the link is pointing to a codebase that is accessible (e.g. not a private repository). "[example.com](http://example.com/)", "n/a", "will add later", etc. are not acceptable links -- we need to see a public codebase. See the above section for accepted links.

### **What happens if I don't provide a sufficient minimal reproduction?**

Issues with the `incomplete` label that receives no meaningful activity (e.g. new comments with a reproduction link) are automatically closed and locked after 30 days.

If your issue has _not_ been resolved in that time and it has been closed/locked, please open a new issue with the required reproduction.

### **I did not open this issue, but it is relevant to me, what can I do to help?**

Anyone experiencing the same issue is welcome to provide a minimal reproduction following the above steps. Furthermore, you can upvote the issue using the :+1: reaction on the topmost comment (please **do not** comment "I have the same issue" without repro steps). Then, we can sort issues by votes to prioritize.

### **I think my reproduction is good enough, why aren't you looking into it quicker?**

We look into every NextAuth.js issue and constantly monitor open issues for new comments.

However, sometimes we might miss one or two. We apologize, and kindly ask you to refrain from tagging core maintainers, as that will usually not result in increased priority.

Upvoting issues to show your interest will help us prioritize and address them as quickly as possible. That said, every issue is important to us, and if an issue gets closed by accident, we encourage you to open a new one linking to the old issue and we will look into it.

### **Useful Resources**

- [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve)
- [Reporting a NextAuth.js bug](https://github.com/nextauthjs/next-auth/blob/main/.github/ISSUE_TEMPLATE/1_bug_framework.yml)
- [How to Contribute to Open Source (Next.js)](https://www.youtube.com/watch?v=cuoNzXFLitc)

88 changes: 88 additions & 0 deletions .github/actions/issue-validator/src/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// @ts-check
// @ts-expect-error
import * as github from "@actions/github"
// @ts-expect-error
import * as core from "@actions/core"
import { readFileSync } from "node:fs"
import { join } from "node:path"

const addReproductionLabel = "incomplete"
const __dirname =
"/home/runner/work/nextauthjs/next-auth/.github/actions/issue-validator"

/**
* @typedef {{
* id :number
* node_id :string
* url :string
* name :string
* description :string
* color :string
* default :boolean
* }} Label
*
* @typedef {{
* pull_request: any
* issue?: {body: string, number: number, labels: Label[]}
* label: Label
* }} Payload
*
* @typedef {{
* payload: Payload
* repo: any
* }} Context
*/

async function run() {
try {
/** @type {Context} */
const { payload, repo } = github.context
const {
issue,
pull_request,
label: { name: newLabel },
} = payload

if (pull_request || !issue?.body || !process.env.GITHUB_TOKEN) return

const labels = issue.labels.map((l) => l.name)
// const isBugReport =
// labels.includes(bugLabel) || newLabel === bugLabel || !labels.length

if (
// !(isBugReport && issue.number > 43554) &&
![addReproductionLabel].includes(newLabel) &&
!labels.includes(addReproductionLabel)
) {
return core.info(
"Not a bug report or not manually labeled or already labeled."
)
}

const client = github.getOctokit(process.env.GITHUB_TOKEN).rest
const issueCommon = { ...repo, issue_number: issue.number }

if (
newLabel === addReproductionLabel
// || !hasValidRepro
) {
await Promise.all([
client.issues.addLabels({
...issueCommon,
labels: [addReproductionLabel],
}),
client.issues.createComment({
...issueCommon,
body: readFileSync(join(__dirname, "repro.md"), "utf8"),
}),
])
return core.info(
"Commented on issue, because it did not have a sufficient reproduction."
)
}
} catch (error) {
core.setFailed(error.message)
}
}

run()
File renamed without changes.
17 changes: 17 additions & 0 deletions .github/workflows/issue-validator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Validate issue
on:
issues:
types: [labeled]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: 'Run issue validator'
run: node ./.github/actions/issue-validator/index.mjs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
File renamed without changes.
140 changes: 71 additions & 69 deletions apps/dev/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,39 @@
import { AuthHandler, AuthOptions } from "next-auth-core"

// Providers
// import Apple from "next-auth/providers/apple"
import Auth0 from "next-auth/providers/auth0"
// import AzureAD from "next-auth/providers/azure-ad"
// import AzureB2C from "next-auth/providers/azure-ad-b2c"
// import BoxyHQSAML from "next-auth/providers/boxyhq-saml"
// import Cognito from "next-auth/providers/cognito"
import Credentials from "next-auth/providers/credentials"
// import Discord from "next-auth/providers/discord"
// import DuendeIDS6 from "next-auth/providers/duende-identity-server6"
// import Email from "next-auth/providers/email"
// import Facebook from "next-auth/providers/facebook"
// import Foursquare from "next-auth/providers/foursquare"
// import Freshbooks from "next-auth/providers/freshbooks"
import GitHub from "next-auth/providers/github"
// import Gitlab from "next-auth/providers/gitlab"
// import Google from "next-auth/providers/google"
// import IDS4 from "next-auth/providers/identity-server4"
// import Instagram from "next-auth/providers/instagram"
// import Keycloak from "next-auth/providers/keycloak"
// import Line from "next-auth/providers/line"
// import LinkedIn from "next-auth/providers/linkedin"
// import Mailchimp from "next-auth/providers/mailchimp"
// import Okta from "next-auth/providers/okta"
// import Osu from "next-auth/providers/osu"
// import Patreon from "next-auth/providers/patreon"
// import Slack from "next-auth/providers/slack"
// import Spotify from "next-auth/providers/spotify"
// import Trakt from "next-auth/providers/trakt"
// import Twitch from "next-auth/providers/twitch"
// import Twitter, { TwitterLegacy } from "next-auth/providers/twitter"
// import Vk from "next-auth/providers/vk"
// import Wikimedia from "next-auth/providers/wikimedia"
// import WorkOS from "next-auth/providers/workos"
import Apple from "next-auth-core/providers/apple"
import Auth0 from "next-auth-core/providers/auth0"
import AzureAD from "next-auth-core/providers/azure-ad"
import AzureB2C from "next-auth-core/providers/azure-ad-b2c"
import BoxyHQSAML from "next-auth-core/providers/boxyhq-saml"
// import Cognito from "next-auth-core/providers/cognito"
import Credentials from "next-auth-core/providers/credentials"
import Discord from "next-auth-core/providers/discord"
import DuendeIDS6 from "next-auth-core/providers/duende-identity-server6"
// import Email from "next-auth-core/providers/email"
import Facebook from "next-auth-core/providers/facebook"
import Foursquare from "next-auth-core/providers/foursquare"
import Freshbooks from "next-auth-core/providers/freshbooks"
import GitHub from "next-auth-core/providers/github"
import Gitlab from "next-auth-core/providers/gitlab"
import Google from "next-auth-core/providers/google"
// import IDS4 from "next-auth-core/providers/identity-server4"
import Instagram from "next-auth-core/providers/instagram"
// import Keycloak from "next-auth-core/providers/keycloak"
import Line from "next-auth-core/providers/line"
import LinkedIn from "next-auth-core/providers/linkedin"
import Mailchimp from "next-auth-core/providers/mailchimp"
// import Okta from "next-auth-core/providers/okta"
import Osu from "next-auth-core/providers/osu"
import Patreon from "next-auth-core/providers/patreon"
import Slack from "next-auth-core/providers/slack"
import Spotify from "next-auth-core/providers/spotify"
import Trakt from "next-auth-core/providers/trakt"
import Twitch from "next-auth-core/providers/twitch"
import Twitter, { TwitterLegacy } from "next-auth-core/providers/twitter"
import Vk from "next-auth-core/providers/vk"
import Wikimedia from "next-auth-core/providers/wikimedia"
import WorkOS from "next-auth-core/providers/workos"

// // Prisma
// import { PrismaClient } from "@prisma/client"
Expand Down Expand Up @@ -82,42 +82,42 @@ export const authOptions: AuthOptions = {
return { name: "Fill Murray", email: "bill@fillmurray.com", image: "https://www.fillmurray.com/64/64", id: "1", foo: "" }
},
}),
// Apple({ clientId: process.env.APPLE_ID, clientSecret: process.env.APPLE_SECRET }),
Apple({ clientId: process.env.APPLE_ID, clientSecret: process.env.APPLE_SECRET }),
Auth0({ clientId: process.env.AUTH0_ID, clientSecret: process.env.AUTH0_SECRET, issuer: process.env.AUTH0_ISSUER }),
// AzureAD({
// clientId: process.env.AZURE_AD_CLIENT_ID,
// clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
// tenantId: process.env.AZURE_AD_TENANT_ID,
// }),
// AzureB2C({ clientId: process.env.AZURE_B2C_ID, clientSecret: process.env.AZURE_B2C_SECRET, issuer: process.env.AZURE_B2C_ISSUER }),
// BoxyHQSAML({ issuer: "https://jackson-demo.boxyhq.com", clientId: "tenant=boxyhq.com&product=saml-demo.boxyhq.com", clientSecret: "dummy" }),
AzureAD({
clientId: process.env.AZURE_AD_CLIENT_ID,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
tenantId: process.env.AZURE_AD_TENANT_ID,
}),
AzureB2C({ clientId: process.env.AZURE_B2C_ID, clientSecret: process.env.AZURE_B2C_SECRET, issuer: process.env.AZURE_B2C_ISSUER }),
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 }),
// Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }),
// DuendeIDS6({ clientId: "interactive.confidential", clientSecret: "secret", issuer: "https://demo.duendesoftware.com" }),
// 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 }),
Discord({ clientId: process.env.DISCORD_ID, clientSecret: process.env.DISCORD_SECRET }),
DuendeIDS6({ clientId: "interactive.confidential", clientSecret: "secret", issuer: "https://demo.duendesoftware.com" }),
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 }),
// Gitlab({ clientId: process.env.GITLAB_ID, clientSecret: process.env.GITLAB_SECRET }),
// Google({ clientId: process.env.GOOGLE_ID, clientSecret: process.env.GOOGLE_SECRET }),
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 }),
// Instagram({ clientId: process.env.INSTAGRAM_ID, clientSecret: process.env.INSTAGRAM_SECRET }),
Instagram({ clientId: process.env.INSTAGRAM_ID, clientSecret: process.env.INSTAGRAM_SECRET }),
// Keycloak({ clientId: process.env.KEYCLOAK_ID, clientSecret: process.env.KEYCLOAK_SECRET, issuer: process.env.KEYCLOAK_ISSUER }),
// Line({ clientId: process.env.LINE_ID, clientSecret: process.env.LINE_SECRET }),
// LinkedIn({ clientId: process.env.LINKEDIN_ID, clientSecret: process.env.LINKEDIN_SECRET }),
// Mailchimp({ clientId: process.env.MAILCHIMP_ID, clientSecret: process.env.MAILCHIMP_SECRET }),
Line({ clientId: process.env.LINE_ID, clientSecret: process.env.LINE_SECRET }),
LinkedIn({ clientId: process.env.LINKEDIN_ID, clientSecret: process.env.LINKEDIN_SECRET }),
Mailchimp({ clientId: process.env.MAILCHIMP_ID, clientSecret: process.env.MAILCHIMP_SECRET }),
// Okta({ clientId: process.env.OKTA_ID, clientSecret: process.env.OKTA_SECRET, issuer: process.env.OKTA_ISSUER }),
// Osu({ clientId: process.env.OSU_CLIENT_ID, clientSecret: process.env.OSU_CLIENT_SECRET }),
// Patreon({ clientId: process.env.PATREON_ID, clientSecret: process.env.PATREON_SECRET }),
// Slack({ clientId: process.env.SLACK_ID, clientSecret: process.env.SLACK_SECRET }),
// Spotify({ clientId: process.env.SPOTIFY_ID, clientSecret: process.env.SPOTIFY_SECRET }),
// Trakt({ clientId: process.env.TRAKT_ID, clientSecret: process.env.TRAKT_SECRET }),
// Twitch({ clientId: process.env.TWITCH_ID, clientSecret: process.env.TWITCH_SECRET }),
// Twitter({ version: "2.0", clientId: process.env.TWITTER_ID, clientSecret: process.env.TWITTER_SECRET }),
Osu({ clientId: process.env.OSU_CLIENT_ID, clientSecret: process.env.OSU_CLIENT_SECRET }),
Patreon({ clientId: process.env.PATREON_ID, clientSecret: process.env.PATREON_SECRET }),
Slack({ clientId: process.env.SLACK_ID, clientSecret: process.env.SLACK_SECRET }),
Spotify({ clientId: process.env.SPOTIFY_ID, clientSecret: process.env.SPOTIFY_SECRET }),
Trakt({ clientId: process.env.TRAKT_ID, clientSecret: process.env.TRAKT_SECRET }),
Twitch({ clientId: process.env.TWITCH_ID, clientSecret: process.env.TWITCH_SECRET }),
Twitter({ version: "2.0", clientId: process.env.TWITTER_ID, clientSecret: process.env.TWITTER_SECRET }),
// TwitterLegacy({ clientId: process.env.TWITTER_LEGACY_ID, clientSecret: process.env.TWITTER_LEGACY_SECRET }),
// Vk({ clientId: process.env.VK_ID, clientSecret: process.env.VK_SECRET }),
// Wikimedia({ clientId: process.env.WIKIMEDIA_ID, clientSecret: process.env.WIKIMEDIA_SECRET }),
// WorkOS({ clientId: process.env.WORKOS_ID, clientSecret: process.env.WORKOS_SECRET }),
Vk({ clientId: process.env.VK_ID, clientSecret: process.env.VK_SECRET }),
Wikimedia({ clientId: process.env.WIKIMEDIA_ID, clientSecret: process.env.WIKIMEDIA_SECRET }),
WorkOS({ clientId: process.env.WORKOS_ID, clientSecret: process.env.WORKOS_SECRET }),
],
}

Expand All @@ -130,19 +130,21 @@ if (authOptions.adapter) {
// )
}

// TODO: move
// TODO: move to next-auth/edge
function Auth(...args: any[]) {
if (args.length === 1)
return async (req: Request) => {
args[0].secret ??= process.env.NEXTAUTH_SECRET
const res = await AuthHandler(req, args[0])

// If the request expects a return URL, send it as JSON
// instead of doing an actual redirect.
const redirect = res.headers.get("Location") || /* TODO: remove */ (await req.json().json)
if (req.headers.get("X-Auth-Return-Redirect") && redirect) {
// TODO: remove when `next-auth/react` sends `X-Auth-Return-Redirect`
const shouldRedirect = req.method === "POST" && req.headers.get("Content-Type") === "application/json" ? (await req.clone().json()).json : false

// TODO: This can be directly in core
const res = await AuthHandler(req, args[0])
if (req.headers.get("X-Auth-Return-Redirect") || shouldRedirect) {
const url = res.headers.get("Location")
res.headers.delete("Location")
return new Response(JSON.stringify({ url: redirect }), res)
return new Response(JSON.stringify({ url }), res)
}
return res
}
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/configuration/nextjs.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,10 @@ You can also use `unstable_getServerSession` in Next.js' server components:

```tsx
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"

export default async function Page() {
const session = await unstable_getServerSession()
const session = await unstable_getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
```
Expand Down
20 changes: 15 additions & 5 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@
"Thang Huu Vu <thvu@hey.com>",
"Iain Collins <me@iaincollins.com"
],
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./providers/*": {
"import": "./dist/providers/*.js",
"types": "./dist/providers/*.d.ts"
}
},
"license": "ISC",
"dependencies": {
"@panva/hkdf": "1.0.2",
Expand All @@ -34,8 +44,9 @@
}
},
"scripts": {
"build": "tsc",
"dev": "tsc -w",
"build": "tsc && pnpm css",
"css": "node ./scripts/generate-css.js",
"dev": "pnpm css && tsc -w",
"test": "jest"
},
"devDependencies": {
Expand All @@ -46,7 +57,6 @@
"autoprefixer": "10.4.13",
"cssnano": "5.1.14",
"postcss": "8.4.19",
"postcss-cli": "10.1.0",
"postcss-nested": "6.0.0"
}
}
Loading

0 comments on commit 59d6385

Please sign in to comment.