Open BaileyMillerSSI opened 1 year ago
Follow up question, does this provider even work?
Upon further investigation my short answer is no. Something is wrong deeper into the NextAuth logic then I can follow or configure. I've written a custom OAuth provider that gets through the token retrieval and then afterwards NextAuth tanks and I have no clue as to why. The same issue happens when using the default Bungie provider.
[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error expected 200 OK, got: 500 Internal Server Error {
error: OPError: expected 200 OK, got: 500 Internal Server Error
at processResponse ({ProjectPath}node_modules\openid-client\lib\helpers\process_response.js:41:11)
at Client.userinfo ({ProjectPath}node_modules\openid-client\lib\client.js:1237:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async oAuthCallback ({ProjectPath}node_modules\next-auth\core\lib\oauth\callback.js:131:17)
at async Object.callback ({ProjectPath}node_modules\next-auth\core\routes\callback.js:52:11)
at async AuthHandler ({ProjectPath}node_modules\next-auth\core\index.js:201:28)
at async NextAuthHandler ({ProjectPath}node_modules\next-auth\next\index.js:24:19)
at async {ProjectPath}node_modules\next-auth\next\index.js:60:32
at async Object.apiResolver ({ProjectPath}node_modules\next\dist\server\api-utils\node.js:372:9)
at async DevServer.runApi ({ProjectPath}node_modules\next\dist\server\next-server.js:514:9)
at async Object.fn ({ProjectPath}node_modules\next\dist\server\next-server.js:828:35)
at async Router.execute ({ProjectPath}node_modules\next\dist\server\router.js:243:32)
at async DevServer.runImpl ({ProjectPath}node_modules\next\dist\server\base-server.js:432:29)
at async DevServer.run ({ProjectPath}node_modules\next\dist\server\dev\next-dev-server.js:831:20)
at async DevServer.handleRequestImpl ({ProjectPath}node_modules\next\dist\server\base-server.js:375:20)
at async {ProjectPath}node_modules\next\dist\server\base-server.js:157:99 {
name: 'OAuthCallbackError',
code: undefined
},
providerId: 'bungie',
message: 'expected 200 OK, got: 500 Internal Server Error'
I have it working with v3.29.10, but have not got it working with v4
Ah good so I'm not crazy it just doesn't work. I'll see about bumping my version down for the project I'm working on.
I plan to put this in a PR at some point when I have some down time, but I managed to get it working in v4 with some additional config:
BungieProvider({
clientId: process.env.BUNGIE_CLIENT_ID,
clientSecret: process.env.BUNGIE_CLIENT_SECRET,
// The Bungie API doesn't like scope being set
authorization: { params: { scope: '' } },
httpOptions: { headers: { 'X-API-Key': process.env.BUNGIE_API_KEY } },
// Correctly gets the current user info so that the existing `profile` definition works
userinfo: {
async request({ tokens, provider }) {
return await fetch(
'https://www.bungie.net/platform/User/GetMembershipsForCurrentUser',
{
headers: {
...provider.httpOptions.headers,
authorization: `Bearer ${tokens.access_token}`
}
}
).then(async response => await response.json())
}
}
})
Awesome, I'll give that a try maybe this week. I am not familiar with this library but a better error message would have been very helpful too. It would be nice if the error said something along the lines of "Error loading user info from provider Bungie".
Hey all, also using the BungieProvider with a new T3 application with the exact same setup as above. I'm running into the following issue:
[next-auth][error][OAUTH_CALLBACK_ERROR]
https://next-auth.js.org/errors#oauth_callback_error State cookie was missing. {
error: TypeError: State cookie was missing.
at Object.use (/Users/rhs_air/dev/d2builds/node_modules/next-auth/core/lib/oauth/checks.js:103:23)
at oAuthCallback (/Users/rhs_air/dev/d2builds/node_modules/next-auth/core/lib/oauth/callback.js:89:25)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Object.callback (/Users/rhs_air/dev/d2builds/node_modules/next-auth/core/routes/callback.js:52:11)
at async AuthHandler (/Users/rhs_air/dev/d2builds/node_modules/next-auth/core/index.js:201:28)
at async NextAuthHandler (/Users/rhs_air/dev/d2builds/node_modules/next-auth/next/index.js:24:19)
at async /Users/rhs_air/dev/d2builds/node_modules/next-auth/next/index.js:60:32
at async Object.apiResolver (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/api-utils/node.js:372:9)
at async DevServer.runApi (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/next-server.js:514:9)
at async Object.fn (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/next-server.js:828:35)
at async Router.execute (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/router.js:243:32)
at async DevServer.runImpl (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/base-server.js:432:29)
at async DevServer.run (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/dev/next-dev-server.js:831:20)
at async DevServer.handleRequestImpl (/Users/rhs_air/dev/d2builds/node_modules/next/dist/server/base-server.js:375:20)
at async /Users/rhs_air/dev/d2builds/node_modules/next/dist/server/base-server.js:157:99 {
name: 'OAuthCallbackError',
code: undefined
},
providerId: 'bungie',
message: 'State cookie was missing.'
}
I check my browser's cookies and it seems that the state cookie is defined. Any idea what could be causing the issue?
This is working for me:
interface IBungieNetUser {
membershipId: number;
uniqueName: string;
displayName: string;
profilePicture: number;
profileTheme: number;
userTitle: string;
successMessageFlags: string | number;
isDeleted: boolean;
about: string;
firstAccess: string;
lastUpdate: string;
context: {
isFollowing: boolean;
ignoreStatus: {
isIgnored: boolean;
ignoreFlags: boolean;
};
};
xboxDisplayName: string;
showActivity: boolean;
locale: string;
localeInheritDefault: boolean;
showGroupMessaging: boolean;
profilePicturePath: string;
profileThemeName: string;
userTitleDisplay: string;
statusText: string;
statusDate: string;
blizzardDisplayName: string;
steamDisplayName: string;
twitchDisplayName: string;
cachedBungieGlobalDisplayName: string;
cachedBungieGlobalDisplayNameCode: number;
egsDisplayName: string;
}
declare module "next-auth" {
interface Session extends DefaultSession {
user: {} & DefaultSession["user"] & IBungieNetUser;
}
}
declare module "next-auth" {
interface Profile {
Response: {
bungieNetUser: IBungieNetUser;
};
}
}
declare module "next-auth/jwt" {
interface JWT {
bungieUser: IBungieNetUser;
}
}
export const authOptions: NextAuthOptions = {
callbacks: {
async jwt({ token, profile }) {
if (profile) {
token.bungieUser = profile.Response.bungieNetUser;
}
return token;
},
session({ session, token }) {
if (token && session.user) {
session.user = {
...session.user,
...token.bungieUser,
};
}
return session;
},
},
providers: [
BungieProvider({
clientId: env.BUNGIE_CLIENT_ID,
clientSecret: env.BUNGIE_SECRET,
// The Bungie API doesn't like scope being set
authorization: { params: { scope: "" } },
httpOptions: { headers: { "X-API-Key": env.BUNGIE_API_KEY } },
// Correctly gets the current user info so that the existing `profile` definition works
userinfo: {
request: async ({ tokens, provider }) => {
const fetchResult = await fetch(
`${env.BUNGIE_API_ROOT}/Platform/User/GetMembershipsForCurrentUser/`,
{
headers: {
...provider?.httpOptions?.headers,
authorization: `Bearer ${tokens.access_token}`,
},
}
);
return await fetchResult.json();
},
},
}),
],
};
Index page:
const Home: NextPage = () => {
const { data: sessionData } = useSession();
return (
<>
<Head>
<title>Create T3 App</title>
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c]">
{sessionData && (
<div className="pb-5">
<div className="flex flex-col items-center text-center">
{sessionData?.user.image && (
<Image
src={sessionData?.user.image}
unoptimized
width={320}
height={320}
alt="Profile picture"
/>
)}
<p className="text-xl text-white">{sessionData?.user.name}</p>
</div>
<pre className="text-white">
{JSON.stringify(sessionData, null, "\t")}
</pre>
</div>
)}
<button
className="rounded-full bg-white/10 px-10 py-3 font-semibold text-white no-underline transition hover:bg-white/20"
onClick={
sessionData ? () => void signOut() : () => void signIn("bungie")
}
>
{sessionData ? "Sign out" : "Sign in"}
</button>
</main>
</>
);
};
Nope, I still get the same error. FWIW, here is part of my package.json
file for package versions.
"dependencies": {
"@next-auth/prisma-adapter": "^1.0.5",
"@prisma/client": "^4.9.0",
"@tanstack/react-query": "^4.20.2",
"@trpc/client": "^10.9.0",
"@trpc/next": "^10.9.0",
"@trpc/react-query": "^10.9.0",
"@trpc/server": "^10.9.0",
"next": "^13.2.1",
"next-auth": "^4.19.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"superjson": "1.9.1",
"zod": "^3.20.6"
},
"devDependencies": {
"@types/eslint": "^8.21.1",
"@types/node": "^18.14.0",
"@types/prettier": "^2.7.2",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.34.0",
"eslint-config-next": "^13.2.1",
"postcss": "^8.4.14",
"prettier": "^2.8.1",
"prettier-plugin-tailwindcss": "^0.2.1",
"prisma": "^4.9.0",
"tailwindcss": "^3.2.0",
"typescript": "^4.9.5"
},
"ct3aMetadata": {
"initVersion": "7.7.0"
}
Question for you, when you click sign in and get redirected to the Bungie screen do you see state
in the url?
Here is mine:
"dependencies": {
"next": "^13.2.1",
"next-auth": "^4.19.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"zod": "^3.20.6"
},
"devDependencies": {
"@types/eslint": "^8.21.1",
"@types/node": "^18.14.0",
"@types/prettier": "^2.7.2",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@typescript-eslint/eslint-plugin": "^5.53.0",
"@typescript-eslint/parser": "^5.53.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.34.0",
"eslint-config-next": "^13.2.1",
"postcss": "^8.4.14",
"prettier": "^2.8.1",
"prettier-plugin-tailwindcss": "^0.2.1",
"tailwindcss": "^3.2.0",
"typescript": "^4.9.5"
},
"ct3aMetadata": {
"initVersion": "7.7.0"
}
Yes, I do, I think the URL is well-formed as per the docs. Seems like we're on the same versions for almost all of our dependencies.
Here is my complete auth setup:
.env:
# Next Auth
# You can generate a new secret on the command line with:
# openssl rand -base64 32
# https://next-auth.js.org/configuration/options#secret
# NEXTAUTH_SECRET=""
NEXTAUTH_URL=https://localhost:3001 <--- This was important because of the proxy stuff. I am using a C# application to proxy my local development because of the Bungie API requiring even local host to be https.
# Next Auth Bungie Provider
BUNGIE_CLIENT_ID=
BUNGIE_SECRET=
BUNGIE_API_KEY=
# Links
BUNGIE_API_ROOT=https://www.bungie.net
import { type GetServerSidePropsContext } from "next";
import {
getServerSession,
type NextAuthOptions,
type DefaultSession,
} from "next-auth";
import BungieProvider from "next-auth/providers/bungie";
import { env } from "~/env.mjs";
interface IBungieNetUser {
membershipId: number;
uniqueName: string;
displayName: string;
profilePicture: number;
profileTheme: number;
userTitle: string;
successMessageFlags: string | number;
isDeleted: boolean;
about: string;
firstAccess: string;
lastUpdate: string;
context: {
isFollowing: boolean;
ignoreStatus: {
isIgnored: boolean;
ignoreFlags: boolean;
};
};
xboxDisplayName: string;
showActivity: boolean;
locale: string;
localeInheritDefault: boolean;
showGroupMessaging: boolean;
profilePicturePath: string;
profileThemeName: string;
userTitleDisplay: string;
statusText: string;
statusDate: string;
blizzardDisplayName: string;
steamDisplayName: string;
twitchDisplayName: string;
cachedBungieGlobalDisplayName: string;
cachedBungieGlobalDisplayNameCode: number;
egsDisplayName: string;
}
declare module "next-auth" {
interface Session extends DefaultSession {
user: {} & DefaultSession["user"] & IBungieNetUser;
}
}
declare module "next-auth" {
interface Profile {
Response: {
bungieNetUser: IBungieNetUser;
};
}
}
declare module "next-auth/jwt" {
interface JWT {
bungieUser: IBungieNetUser;
}
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
* @see https://next-auth.js.org/configuration/options
*/
export const authOptions: NextAuthOptions = {
callbacks: {
async jwt({ token, profile }) {
if (profile) {
token.bungieUser = profile.Response.bungieNetUser;
}
return token;
},
session({ session, token }) {
if (token && session.user) {
session.user = {
...session.user,
...token.bungieUser,
};
}
return session;
},
},
providers: [
BungieProvider({
clientId: env.BUNGIE_CLIENT_ID,
clientSecret: env.BUNGIE_SECRET,
// The Bungie API doesn't like scope being set
authorization: { params: { scope: "" } },
httpOptions: { headers: { "X-API-Key": env.BUNGIE_API_KEY } },
// Correctly gets the current user info so that the existing `profile` definition works
userinfo: {
request: async ({ tokens, provider }) => {
const fetchResult = await fetch(
`${env.BUNGIE_API_ROOT}/Platform/User/GetMembershipsForCurrentUser/`,
{
headers: {
...provider?.httpOptions?.headers,
authorization: `Bearer ${tokens.access_token}`,
},
}
);
return await fetchResult.json();
},
},
}),
],
};
/**
* Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file.
*
* @see https://next-auth.js.org/configuration/nextjs
*/
export const getServerAuthSession = (ctx: {
req: GetServerSidePropsContext["req"];
res: GetServerSidePropsContext["res"];
}) => {
return getServerSession(ctx.req, ctx.res, authOptions);
};
Alright, found my bug. My .env
file had my NEXTAUTH_URL
still using localhost
rather than127.0.0.1
. This would cause a redirect which would erase the cookie from the link between logins. Thanks for all your help!
Alright, found my bug. My
.env
file had myNEXTAUTH_URL
still usinglocalhost
rather than127.0.0.1
. This would cause a redirect which would erase the cookie from the link between logins. Thanks for all your help!
I'm personally really surprised Bungie requires localhost to be secure which causes us to need to setup a cert and changing defaults. I'm so used to platforms letting localhost be open because it's used for development
Question 💬
I followed the example for adding the Bungie provider here. After doing so I found that the default implementation isn't happy with Typescript.
Argument of type '{ clientId: string; clientSecret: string; headers: { "X-API-Key": string; }; }' is not assignable to parameter of type 'Partial<OAuthConfig<any>>'. Object literal may only specify known properties, and 'headers' does not exist in type 'Partial<OAuthConfig<any>>'.
What is the intended setup when using Typescript with this provider?
How to reproduce ☕️
create t3 app
Contributing 🙌🏽
No, I am afraid I cannot help regarding this.
Unless it is as simple as changing the default to this: