mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
8 Commits
next-auth@
...
next-auth@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fdb0da6eb | ||
|
|
5c4a9a697d | ||
|
|
eddd8fd7f9 | ||
|
|
b74bfc68e8 | ||
|
|
0a140cdf87 | ||
|
|
157269e0fb | ||
|
|
221bc8e99c | ||
|
|
f856363ac8 |
@@ -46,6 +46,10 @@ title: Tutorials and Explainers
|
||||
- Learn how to use Sign-In With Ethereum to authenticate your users with their existing Ethereum wallets - identifiers they personally control.
|
||||
- Example application: [spruceid/siwe-next-auth-example](https://github.com/spruceid/siwe-next-auth-example)
|
||||
|
||||
#### [Next.js Authentication with Okta and NextAuth.js 4.0](https://thetombomb.com/posts/nextjs-nextauth-okta) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
- Learn how to perform authentication with an OIDC Application in Okta and NextAuth.js.
|
||||
|
||||
## Fullstack
|
||||
|
||||
#### [Build a FullStack App with Next.js, NextAuth.js, Supabase & Prisma](https://themodern.dev/courses/build-a-fullstack-app-with-nextjs-supabase-and-prisma-322389284337222224) <svg xmlns="http://www.w3.org/2000/svg" style={{ marginLeft: '5px', marginBottom:'-6px'}} height="20" width="20" fill="none" viewBox="0 0 24 24" stroke="currentColor"><title>External</title> <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /> </svg>
|
||||
|
||||
@@ -14,6 +14,10 @@ If you did not find a guide or tutorial covering your use case, please [open an
|
||||
- How to restrict access to pages and API routes.
|
||||
- [Usage with class components](/tutorials/usage-with-class-components)
|
||||
- How to use `useSession()` hook with class components.
|
||||
- [Next.js Authentication with Okta and NextAuth.js 4.0](https://thetombomb.com/posts/nextjs-nextauth-okta)
|
||||
- Learn how to perform authentication with an OIDC Application in Okta and NextAuth.js.
|
||||
|
||||
|
||||
|
||||
### Advanced
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "next-auth",
|
||||
"version": "4.18.1",
|
||||
"version": "4.18.4",
|
||||
"description": "Authentication for Next.js",
|
||||
"homepage": "https://next-auth.js.org",
|
||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AuthHandler } from "../core"
|
||||
import { getURL, getBody } from "../utils/node"
|
||||
import { getURL, getBody, setHeaders } from "../utils/node"
|
||||
|
||||
import type {
|
||||
GetServerSidePropsContext,
|
||||
@@ -37,10 +37,7 @@ async function NextAuthHandler(
|
||||
const { status, headers } = response
|
||||
res.status(status)
|
||||
|
||||
for (const [key, val] of headers.entries()) {
|
||||
const value = key === "set-cookie" ? val.split(",") : val
|
||||
res.setHeader(key, value)
|
||||
}
|
||||
setHeaders(headers, res)
|
||||
|
||||
// If the request expects a return URL, send it as JSON
|
||||
// instead of doing an actual redirect.
|
||||
@@ -158,10 +155,11 @@ export async function unstable_getServerSession<
|
||||
|
||||
const { status = 200, headers } = response
|
||||
|
||||
for (const [key, val] of headers.entries()) {
|
||||
const value = key === "set-cookie" ? val.split(",") : val
|
||||
res.setHeader(key, value)
|
||||
}
|
||||
setHeaders(headers, res)
|
||||
|
||||
// This would otherwise break rendering
|
||||
// with `getServerSideProps` that needs to always return HTML
|
||||
res.removeHeader?.("Content-Type")
|
||||
|
||||
const data = await response.json()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { IncomingMessage } from "http"
|
||||
import type { IncomingMessage, ServerResponse } from "http"
|
||||
import type { GetServerSidePropsContext, NextApiRequest } from "next"
|
||||
|
||||
export function setCookie(res, value: string) {
|
||||
@@ -43,13 +43,104 @@ export function getURL(
|
||||
}
|
||||
|
||||
if (!host) throw new TypeError("Invalid host")
|
||||
if (!url) throw new TypeError("Invalid URL, cannot determine action")
|
||||
|
||||
return new URL(`${host}${url ?? ""}`)
|
||||
if (host.startsWith("http://") || host.startsWith("https://")) {
|
||||
return new URL(`${host}${url}`)
|
||||
}
|
||||
return new URL(`https://${host}${url}`)
|
||||
} catch (error) {
|
||||
return error as Error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set-Cookie header field-values are sometimes comma joined in one string. This splits them without choking on commas
|
||||
* that are within a single set-cookie field-value, such as in the Expires portion.
|
||||
* This is uncommon, but explicitly allowed - see https://tools.ietf.org/html/rfc2616#section-4.2
|
||||
* Node.js does this for every header *except* set-cookie - see https://github.com/nodejs/node/blob/d5e363b77ebaf1caf67cd7528224b651c86815c1/lib/_http_incoming.js#L128
|
||||
* Based on: https://github.com/google/j2objc/commit/16820fdbc8f76ca0c33472810ce0cb03d20efe25
|
||||
* Credits to: https://github.com/tomball for original and https://github.com/chrusart for JavaScript implementation
|
||||
* @source https://github.com/nfriedly/set-cookie-parser/blob/3eab8b7d5d12c8ed87832532861c1a35520cf5b3/lib/set-cookie.js#L144
|
||||
*/
|
||||
function getSetCookies(cookiesString: string) {
|
||||
if (typeof cookiesString !== "string") {
|
||||
return []
|
||||
}
|
||||
|
||||
const cookiesStrings: string[] = []
|
||||
let pos = 0
|
||||
let start
|
||||
let ch
|
||||
let lastComma: number
|
||||
let nextStart
|
||||
let cookiesSeparatorFound
|
||||
|
||||
function skipWhitespace() {
|
||||
while (pos < cookiesString.length && /\s/.test(cookiesString.charAt(pos))) {
|
||||
pos += 1
|
||||
}
|
||||
return pos < cookiesString.length
|
||||
}
|
||||
|
||||
function notSpecialChar() {
|
||||
ch = cookiesString.charAt(pos)
|
||||
|
||||
return ch !== "=" && ch !== ";" && ch !== ","
|
||||
}
|
||||
|
||||
while (pos < cookiesString.length) {
|
||||
start = pos
|
||||
cookiesSeparatorFound = false
|
||||
|
||||
while (skipWhitespace()) {
|
||||
ch = cookiesString.charAt(pos)
|
||||
if (ch === ",") {
|
||||
// ',' is a cookie separator if we have later first '=', not ';' or ','
|
||||
lastComma = pos
|
||||
pos += 1
|
||||
|
||||
skipWhitespace()
|
||||
nextStart = pos
|
||||
|
||||
while (pos < cookiesString.length && notSpecialChar()) {
|
||||
pos += 1
|
||||
}
|
||||
|
||||
// currently special character
|
||||
if (pos < cookiesString.length && cookiesString.charAt(pos) === "=") {
|
||||
// we found cookies separator
|
||||
cookiesSeparatorFound = true
|
||||
// pos is inside the next cookie, so back up and return it.
|
||||
pos = nextStart
|
||||
cookiesStrings.push(cookiesString.substring(start, lastComma))
|
||||
start = pos
|
||||
} else {
|
||||
// in param ',' or param separator ';',
|
||||
// we continue from that comma
|
||||
pos = lastComma + 1
|
||||
}
|
||||
} else {
|
||||
pos += 1
|
||||
}
|
||||
}
|
||||
|
||||
if (!cookiesSeparatorFound || pos >= cookiesString.length) {
|
||||
cookiesStrings.push(cookiesString.substring(start, cookiesString.length))
|
||||
}
|
||||
}
|
||||
|
||||
return cookiesStrings
|
||||
}
|
||||
|
||||
export function setHeaders(headers: Headers, res: ServerResponse) {
|
||||
for (const [key, val] of headers.entries()) {
|
||||
// See: https://github.com/whatwg/fetch/issues/973
|
||||
const value = key === "set-cookie" ? getSetCookies(val) : val
|
||||
res.setHeader(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace NodeJS {
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import { MissingAPIRoute } from "../src/core/errors"
|
||||
// import { MissingAPIRoute } from "../src/core/errors"
|
||||
import { nodeHandler } from "./utils"
|
||||
|
||||
it("Missing req.url throws MISSING_NEXTAUTH_API_ROUTE_ERROR", async () => {
|
||||
const { res, logger } = await nodeHandler()
|
||||
const { res } = await nodeHandler()
|
||||
|
||||
expect(res.status).toBeCalledWith(500)
|
||||
expect(logger.error).toBeCalledTimes(1)
|
||||
expect(logger.error).toBeCalledWith(
|
||||
"MISSING_NEXTAUTH_API_ROUTE_ERROR",
|
||||
expect.any(MissingAPIRoute)
|
||||
)
|
||||
expect(res.setHeader).toBeCalledWith("content-type", "application/json")
|
||||
const body = res.send.mock.calls[0][0]
|
||||
expect(JSON.parse(body)).toEqual({
|
||||
message:
|
||||
"There is a problem with the server configuration. Check the server logs for more information.",
|
||||
})
|
||||
expect(res.status).toBeCalledWith(400)
|
||||
// Moved to host detection in getUrl
|
||||
// expect(logger.error).toBeCalledTimes(1)
|
||||
// expect(logger.error).toBeCalledWith(
|
||||
// "MISSING_NEXTAUTH_API_ROUTE_ERROR",
|
||||
// expect.any(MissingAPIRoute)
|
||||
// )
|
||||
// expect(res.setHeader).toBeCalledWith("content-type", "application/json")
|
||||
// const body = res.send.mock.calls[0][0]
|
||||
// expect(JSON.parse(body)).toEqual({
|
||||
// message:
|
||||
// "There is a problem with the server configuration. Check the server logs for more information.",
|
||||
// })
|
||||
})
|
||||
|
||||
it("Missing host throws 400 in production", async () => {
|
||||
|
||||
Reference in New Issue
Block a user