Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apple provider broken - blowing up when not finding userinfo endpoint #6788

Closed
kyllerss opened this issue Feb 22, 2023 · 42 comments · Fixed by #12068
Closed

Apple provider broken - blowing up when not finding userinfo endpoint #6788

kyllerss opened this issue Feb 22, 2023 · 42 comments · Fixed by #12068
Labels
bug Something isn't working providers upstream The issue dervies from one of next-auth dependencies

Comments

@kyllerss
Copy link

Provider type

Apple

Environment

System:
OS: Linux 5.19 KDE neon 5.27 5.27
CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz
Memory: 6.74 GB / 15.34 GB
Container: Yes
Shell: 5.1.16 - /bin/bash
Binaries:
Node: 16.18.0 - ~/apps/node-v16.18.0-linux-x64/bin/node
npm: 9.3.0 - ~/apps/node-v16.18.0-linux-x64/bin/npm
Browsers:
Brave Browser: 110.1.48.164
Chrome: 110.0.5481.100
Firefox: 110.0

Reproduction URL

Needed?

Describe the issue

Seems as if Apple another one of those providers that does not provide user info.

When the redirect endpoint is invoked I get the following error:

[auth][cause]: TypeError: TODO: Authorization server did not provide a userinfo endpoint.
     at handleOAuth (file:///xxx/node_modules/@auth/sveltekit/node_modules/@auth/core/lib/oauth/callback.js:28:19)
     ...

The line in question is here.

I found a relevant issue that had a specific work-around, but pertained to Todoist.

Doesn't seem to me that requiring a user-info endpoint is part of the OAuth spec, but I could be wrong. I would rather have this restriction be a configuration option or handled explicitly by some callback. I wouldn't be surprised if the push for privacy is going to push additional partners to follow a similar pattern.

How to reproduce

Try to do a sign-in using Apple.

Expected behavior

For it to work and have the client specify how to handle the missing information.

@kyllerss kyllerss added providers triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Feb 22, 2023
@kyllerss kyllerss changed the title Apple provider not providing userinfo endpoint Apple provider broken - blowing up when not finding userinfo endpoint Feb 22, 2023
@jschlesser
Copy link
Contributor

I'm running into this too. @kyllerss did you find a workaround?

@kyllerss
Copy link
Author

I've put this task aside for now, so I haven't had a chance to do a workaround.

@ChrGrb
Copy link
Contributor

ChrGrb commented Jul 31, 2023

@kyllerss @jschlesser The debug message here is a bit unclear. If you provide a token endpoint, a userinfo endpoint is not necessary.

Additionally the authorization endpoint returns the relevant data only in the body of the response, instead of the query, like Auth.js would expect it. Therefor you have to use response_mode: 'query' for the authorization config. This comes with the downside, that you cannot request the email, or name of the user. I'm currently working on a fix to this.

For now, if you still want to use Sign in with Apple using Auth.js you can use this Apple provider configuration example to get it working:

Apple({
    clientId: APPLE_ID,
    clientSecret: APPLE_SECRET,
    wellKnown: "https://appleid.apple.com/.well-known/openid-configuration",
    checks: ["pkce"],
    token: {
      url: `https://appleid.apple.com/auth/token`,
    },
    authorization: {
      url: 'https://appleid.apple.com/auth/authorize',
      params: {
        scope: '',
        response_type: 'code',
        response_mode: 'query',
        state: crypto.randomUUID()
      },
    },
    client: {
      token_endpoint_auth_method: "client_secret_post",
    },
  })

In addition you'll need to set the secret for jwt encoding and the pkceCodeVerifier cookie on the top level of the auth configuration:

    cookies: {
      pkceCodeVerifier: {
        name: "next-auth.pkce.code_verifier",
        options: {
          httpOnly: true,
          sameSite: "none",
          path: "/",
          secure: true,
        },
      },
    },
    secret: AUTH_SECRET

I hope this helps :)

@Artur-Galstyan
Copy link

Any news on this? @ChrGrb configuration doesn't work for me :(

@RomanistHere
Copy link

@ChrGrb it sort of works, but it doesn't return email/name and setting authorization.params.scope to something other then "" gets other errors.

There is no point using it if you get this:
image

@pingustar
Copy link

so do I understand that it is impossible to get the email and name from apple sign in?

@Jay-flow
Copy link

Jay-flow commented Apr 16, 2024

Any updates?
The same issue still occurs with version 5.0.0-beta.16.
@ChrGrb method enables Apple login but cannot get the name.

How can I get other values defined in the name or scope?

The problem seems to be quite old. Are there any plans to resolve this issue? I like using next-auth and it has been very helpful, so I would like to continue using it. Thank you for creating such a great package.

@glencoden
Copy link

I'm also curious about the state of this issue.

I added 5.0.0-beta.16 with the GitHub provider for proof-of-concept and all went well. But with Apple sign-in I ran into the current issue.
When I saw it was unresolved I downgraded to v4 and ran into #4061, which I also cannot fix atm.

Is there any working example of Apple sign-in using next-auth v4 or v5?

@gordonturner
Copy link

I am also watching this closely, I am only able to use Sign in with Apple for my application, so this is key for me.

I have tried the configuration above from @ChrGrb but am getting a 'checks.state argument is missing', I suspect I am missing something dumb.

@jschlesser
Copy link
Contributor

I've been watching this for a year to see if anyone came up with anything. I gave up on trying to get email from Apple via AuthJS. It's not impossible but in my estimation it looks like it would take a lot of work that's beyond my desire. These notes are for anyone else who is feeling ambitious.

In a nutshell, the valid way that Apple is providing the email scope is only through using the response_mode of 'form_post'. Search for response_mode and response_type in the Apple docs. AuthJS on the other hand only supports 'query' mode. Implementing 'form_post' in AuthJS looks non trivial.

If you want to push for this, I would start a discussion with one of the core contributors like @balazsorban44 or @ThangHuuVu . I'm neither an expert in OAuth nor deeply familiar with all of the nuances that are going on in packages/core/src/lib/[actions|pages]

Otherwise the default Apple provider config should be replaced with the one that @ChrGrb has provided above and in the Apple provider docs clearly let everyone know that they won't be getting the email scope from Apple when using AuthJS.

Note for @balazsorban44 , the docs say that you test 20 or so of the providers and we can try out the sample app. When I click on Sign In on the Apple button (the first one at the top) and try to create an account, it fails no matter which options I choose.

The basis for my findings. Search for 'form_post' in the entire repo. It only shows up in the default Apple provider source file and if you have read through this thread, you will know that the provided Apple default config doesn't work. The workaround that @ChrGrb provided will get you logged in but not an account with the email scope. Note that the response mode is 'query' in that workaround config. Now go back to the Apple docs in the link above and read the section about getting the identity_token and you will see that it's only provided in the modes of 'fragment' or 'form_post'. If you search for 'fragment' in the codebase you will not see it show up in any provider code. The user section and identity_token of the response are the only ways to get email, and they must be requested in the scope and that cant be done with 'query' mode with Apple. In the back of my mind I can hear a security guy at Apple telling the authentication team to not put email in the url, because it seems like the right call. On the other hand it seems like Apple is the only player not using 'query'.

Does anyone see any other way?

@gordonturner
Copy link

gordonturner commented Apr 20, 2024

Hey @jschlesser I believe your details with regards to the Sign in with Apple are correct, I have a working implementation in Python FastAPI, and my experience there is consistent with your comments.

The only other thing I would add (or call out explicitly) is that userInfo is only returned from the first Sign in with Apple request.

In order to get the userInfo details again, you must go to https://appleid.apple.com/ and remove the app in 'Sign in with Apple' section.

Question, are the changes from #8189 (or equivalent) in the latest build or beta build?

If we apply that patch ourselves to the latest code, can we get things working/is that a good approach?
I see the 8189 pull/patch is quite out of date, so there is rebasing required.

@bsin1
Copy link

bsin1 commented May 6, 2024

Until the apple provider is fixed I was able to get this working by adding an override route to handle the apple callback.

// app/api/auth/[...nextauth]/route.ts

import { handlers } from 'auth'

export const { GET, POST } = handlers
// app/api/auth/callback/apple/route.ts

import { NextRequest, NextResponse } from 'next/server'
import { GET as NextAuthGET } from '../../[...nextauth]/route'

// re-export the next-auth GET handler for this endpoint.
export { NextAuthGET as GET } 

export async function POST(req: NextRequest) {

  // contains user name and email if you need to process anything.
  const data = await req.formData() 

  const queryParams: { [key: string]: string } = {}
  data.forEach((value, key) => {
    queryParams[key] = value.toString()
  })

  const searchParams = new URLSearchParams(queryParams)

  const cookie = req.headers.get('cookie') || ''

  // redirect to the next-auth handler which expects GET with query params. 
  return NextResponse.redirect(
    `https://${req.headers.get('host')}/api/auth/callback/apple?` +
      searchParams.toString(),
    {
      status: 302,
      headers: {
        cookie,
      },
    },
  )
}

@glencoden
Copy link

Until the apple provider is fixed I was able to get this working by adding an override route to handle the apple callback.

// app/api/auth/[...nextauth]/route.ts

import { handlers } from 'auth'

export const { GET, POST } = handlers
// app/api/auth/callback/apple/route.ts

import { NextRequest, NextResponse } from 'next/server'
import { GET as NextAuthGET } from '../../[...nextauth]/route'

// re-export the next-auth GET handler for this endpoint.
export { NextAuthGET as GET } 

export async function POST(req: NextRequest) {

  // contains user name and email if you need to process anything.
  const data = await req.formData() 

  const queryParams: { [key: string]: string } = {}
  data.forEach((value, key) => {
    queryParams[key] = value.toString()
  })

  const searchParams = new URLSearchParams(queryParams)

  const cookie = req.headers.get('cookie') || ''

  // redirect to the next-auth handler which expects GET with query params. 
  return NextResponse.redirect(
    `https://${req.headers.get('host')}/api/auth/callback/apple?` +
      searchParams.toString(),
    {
      status: 302,
      headers: {
        cookie,
      },
    },
  )
}

I tried this route handler, but the authentication process seems still to be missing the email address from the Apple account. Here's the error log from the related Vercel function:

�[31m[auth][cause]�[0m: u: null value in column "email" of relation "user" violates not-null constraint at K (/var/task/.next/server/chunks/458.js:420:2291) at /var/task/.next/server/chunks/458.js:420:3320 at Socket.eQ (/var/task/.next/server/chunks/458.js:420:3325) at Socket.emit (node:events:517:28) at addChunk (node:internal/streams/readable:368:12) at readableAddChunk (node:internal/streams/readable:341:9) at Readable.push (node:internal/streams/readable:278:10) at TCP.onStreamRead (node:internal/stream_base_commons:190:23) at TCP.callbackTrampoline (node:internal/async_hooks:128:17)

@bsin1
Copy link

bsin1 commented May 15, 2024

@glencoden as @gordonturner mentioned the user's email will only be delivered the first time they sign in. Subsequent sign ins will deliver the apple sub which is used to retrieve an account by id along with the associated user. After signing in with apple are you prompted to share or mask your email address?

I'm not sure what your adapter looks like but the PrismaAdapter is working fine out of the box for me with 5.0.0-beta.17

@ThangHuuVu
Copy link
Member

ThangHuuVu commented Jun 8, 2024

Hey everyone, thanks for discussing about this issue. I want to summarize the findings & workaround so far to track it better. I believe there are some separate issues that are happening at once, and we can deal with them one by one before getting the Apple provider working.

Issue 1: @auth/core is throwing an error: TypeError: TODO: Authorization server did not provide a userinfo endpoint.

if (!discoveredAs.userinfo_endpoint)
throw new TypeError(
"TODO: Authorization server did not provide a userinfo endpoint."
)

See Apple's .well-known. @auth/core is requiring userinfo_endpoint although it is technically optional from the spec. I might be wrong here. I read through the OpenID Connect Core Spec, but couldn't find the linfo about the userinfo endpoint being required for the Authorization Server.

Plan to fix: I will confirm with @balazsorban44 before raising a PR

Issue 2: Apple requires response_mode=form_post in the Authorization request if requesting for any scopes

Thanks @jschlesser for pointing to this info on the Apple documentation page. Currently, @auth/core isn't supporting the response_mode=form_post.
Plan to fix: @ChrGrb raised a PR to fix here: #8428

Issue 3: Apple isn't returning the claims in id_token

Auth.js normally expects the claims are in id_token if the provider is OIDC type.

profile = o.getValidatedIdTokenClaims(result)

Instead, Apple returns the user info as a JSON string in the query params, for reasons only they know. This is not an issue with Auth.js.

Workaround

To workaround the issues, you can use patch-package following this PR change: #8189. You could check the PR comments for details of why we haven't merged it yet.

Hope that helps. I also confirm that our deployed example isn't working as expected at the moment. The Apple provider is indeed annoying to work with:

  • It requires a fee for a developer account.
  • The account then requires 2FA on phone only, which makes it even harder to share the account between contributors

@ThangHuuVu ThangHuuVu added bug Something isn't working upstream The issue dervies from one of next-auth dependencies and removed triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Jun 9, 2024
@mamimotu
Copy link

mamimotu commented Jun 15, 2024

To everyone facing issues with the Apple provider not providing a userinfo endpoint, here's a workaround to get it functioning correctly with NextAuth.js:

Configuration for Apple Provider in NextAuth.js

  1. Configure the Apple provider in your NextAuth.js configuration file, typically found in pages/api/auth/[...nextauth].ts:
import NextAuth from "next-auth"
  import Providers from "next-auth/providers"

  export default NextAuth({
    providers: [
      Providers.Apple({
        clientId: process.env.APPLE_ID,
        clientSecret: process.env.APPLE_SECRET,
        wellKnown: "https://appleid.apple.com/.well-known/openid-configuration",
        checks: ["pkce"],
        authorization: {
          url: 'https://appleid.apple.com/auth/authorize',
          params: {
            scope: "name email",
            response_type: "code",
            response_mode: "form_post",
            state: crypto.randomUUID(),
          },
        },
        token: {
          url: `https://appleid.apple.com/auth/token`,
        },
        client: {
          token_endpoint_auth_method: "client_secret_post",
        },
        profile(profile) {
          return {
            id: profile.sub,
            name: profile.name || null,
            email: profile.email || null,
            image: null,
          }
        },
        profileConform(profile, query) {
          if (query.user) {
            const user = JSON.parse(query.user);
            if (user.name) {
              profile.name = Object.values(user.name).join(" ");
            }
          }
          return profile;
        },
      }),
    ],
    session: {
      jwt: true,
    },
    jwt: {
      secret: process.env.AUTH_SECRET,
    },
    },
  })`

Override the Apple Callback Route

To handle the Apple callback correctly, create an override route for the Apple callback:

  1. Create a file at pages/api/auth/callback/apple.ts:


    import { NextRequest, NextResponse } from 'next/server'
    import { GET as NextAuthGET } from '../../[...nextauth]'

    export { NextAuthGET as GET }

    export async function POST(req: NextRequest) {
      const data = await req.formData();
      const queryParams: { [key: string]: string } = {};
      data.forEach((value, key) => {
        queryParams[key] = value.toString();
      });

      const searchParams = new URLSearchParams(queryParams);
      const cookie = req.headers.get('cookie') || '';

      return NextResponse.redirect(
        `https://${req.headers.get('host')}/api/auth/callback/apple?${searchParams.toString()}`,
        {
          status: 302,
          headers: {
            cookie,
          },
       
      );
    }


Explanation:

  • Apple Provider Configuration:

    • The authorization parameter includes response_mode: "form_post" to comply with Apple's requirements.
    • The profileConform function processes the user information returned in the authorization response.
  • Session and JWT:

    • The session is configured to use JWT, and the jwt configuration includes the secret required for encoding.
  • PKCE Code Verifier Cookie:

    • A custom cookie configuration for pkceCodeVerifier to handle the PKCE flow securely.
  • Handling the Apple Callback:

    • The POST handler processes the form data returned from Apple, converts it to query parameters, and redirects it to the NextAuth.js handler with the necessary cookies.

By following these steps, you should be able to implement a workaround for the Apple provider issue in NextAuth.js until a permanent fix is merged into the library.

@kiikoh
Copy link

kiikoh commented Jul 22, 2024

Any idea when this will be updated to work by default?

@sl45sms
Copy link

sl45sms commented Aug 4, 2024

Thanks to all for workarounds here.
Just for reference, on latest beta 5.0.0-beta.20 thanks to @ChrGrb and #8428 there not need to override callback.
In my case I decided not to try to get the name, and just allow user to change it.
Here is my working configuration

export const authConfig = {
  cookies: {
    pkceCodeVerifier: {
      name: "next-auth.pkce.code_verifier",
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
     },
  },
  providers: [
    GitHub,
    Google,
    Apple({
      clientId: process.env.AUTH_APPLE_ID,
      clientSecret: ""+process.env.AUTH_APPLE_SECRET,
      checks: ["pkce"],
      token: {
        url: `https://appleid.apple.com/auth/token`,
      },
      client: {
        token_endpoint_auth_method: "client_secret_post",
      },
      authorization: {
        params: {
          response_mode: "form_post",
          response_type: "code",//do not set to "code id_token" as it will not work
          scope: "name email"
        },},
        profile(profile) {
          return {
            id: profile.sub,
            name: "Person Doe",//profile.name.givenName + " " + profile.name.familyName, but apple does not return name...
            email: profile.email,
            image: "",
          }
        }
    }),
}

@lucassalicanorc
Copy link

@sl45sms your working configuration works great, thank you!

@boehmbe
Copy link

boehmbe commented Aug 10, 2024

@sl45sms thx, saved my day!

@kiikoh
Copy link

kiikoh commented Aug 10, 2024

I am getting this error, I believe because I am using the AUTH_REDIRECT_PROXY documented here. https://authjs.dev/getting-started/deployment#securing-a-preview-deployment

InvalidCheck: Missing state in query, but required for redirect proxy. Read more at https://errors.authjs.dev#invalidcheck

Also, getting this error in production where the redirect proxy should be used

Error: TODO: Handle OIDC response body error.

I am using https://github.com/t3-oss/create-t3-turbo as a starter. I need to implement apple auth before I can publish to the app store so this is a major blocker, I believe for all of the project using this template.

Is there another workaround?

@sl45sms
Copy link

sl45sms commented Aug 10, 2024

I am getting this error, I believe because I am using the AUTH_REDIRECT_PROXY documented here. https://authjs.dev/getting-started/deployment#securing-a-preview-deployment

InvalidCheck: Missing state in query, but required for redirect proxy. Read more at https://errors.authjs.dev#invalidcheck

Also, getting this error in production where the redirect proxy should be used

Error: TODO: Handle OIDC response body error.

I am using https://github.com/t3-oss/create-t3-turbo as a starter. I need to implement apple auth before I can publish to the app store so this is a major blocker, I believe for all of the project using this template.

Is there another workaround?
@kiikoh Try to set state cookie with samesite none (as pkceCodeVerifier do)

@kiikoh
Copy link

kiikoh commented Aug 10, 2024

@sl45sms I have update my config to include this, in both the proxy and the nextjs route

cookies: {
    pkceCodeVerifier: {
      name: "next-auth.pkce.code_verifier",
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
    },
    state: {
		// do i need to add a name? what should it be
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
    },
  },

Still seeing the same errors

In production, without the proxy

Error: TODO: Handle OIDC response body error
  at ig (/var/task/apps/nextjs/.next/server/chunks/621.js:393:29432)
  at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
  at async iP (/var/task/apps/nextjs/.next/server/chunks/621.js:393:35570)
  at async iU (/var/task/apps/nextjs/.next/server/chunks/621.js:393:47370)
  at async iK (/var/task/apps/nextjs/.next/server/chunks/621.js:393:52671)
  at async /var/task/apps/nextjs/.next/server/chunks/189.js:13:50805
  at async /var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:34666
  at async eS.execute (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:25813)
  at async eS.handle (/var/task/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:35920)
  at async es (/var/task/node_modules/next/dist/compiled/next-server/server.runtime.prod.js:16:25461)

And
Missing state in query, but required for redirect proxy on local development, which uses the proxy

Thank you for taking a look into this

@sl45sms
Copy link

sl45sms commented Aug 11, 2024

@kiikoh are you sure you have set the correct clientId? I had some strange problems because of this, which didn't seem to be related at all.

@kiikoh
Copy link

kiikoh commented Aug 11, 2024

@kiikoh are you sure you have set the correct clientId? I had some strange problems because of this, which didn't seem to be related at all.

I'm pretty sure it's the correct client id because on apples login page it shows my app name.

image
@sl45sms

@sl45sms
Copy link

sl45sms commented Aug 11, 2024

@kiikoh apple call this as "serviceID" and you can found it under https://developer.apple.com/account/resources/identifiers/list/serviceId
looks like
Στιγμιότυπο οθόνης 2024-08-11, 18 25 12
in my case is "ai.prompt2" may you use the app id

@kiikoh
Copy link

kiikoh commented Aug 11, 2024

@kiikoh apple call this as "serviceID" and you can found it under developer.apple.com/account/resources/identifiers/list/serviceId looks like Στιγμιότυπο οθόνης 2024-08-11, 18 25 12 in my case is "ai.prompt2" may you use the app id

@sl45sms right, I was just saying that since that text appeared, and I didn't manually enter that in it must have picked it up correctly. Everything works up until the redirect back to my app.

image

In my env I have, AUTH_APPLE_ID=com.musicbridge.authsrv

@larryhopecode
Copy link

larryhopecode commented Aug 29, 2024

Thanks to all for workarounds here. Just for reference, on latest beta 5.0.0-beta.20 thanks to @ChrGrb and #8428 there not need to override callback. In my case I decided not to try to get the name, and just allow user to change it. Here is my working configuration

export const authConfig = {
  cookies: {
    pkceCodeVerifier: {
      name: "next-auth.pkce.code_verifier",
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
     },
  },
  providers: [
    GitHub,
    Google,
    Apple({
      clientId: process.env.AUTH_APPLE_ID,
      clientSecret: ""+process.env.AUTH_APPLE_SECRET,
      checks: ["pkce"],
      token: {
        url: `https://appleid.apple.com/auth/token`,
      },
      client: {
        token_endpoint_auth_method: "client_secret_post",
      },
      authorization: {
        params: {
          response_mode: "form_post",
          response_type: "code",//do not set to "code id_token" as it will not work
          scope: "name email"
        },},
        profile(profile) {
          return {
            id: profile.sub,
            name: "Person Doe",//profile.name.givenName + " " + profile.name.familyName, but apple does not return name...
            email: profile.email,
            image: "",
          }
        }
    }),
}

Got a new type of error in /api/aut/callback/apple

AccessDenied: AccessDenied. Read more at https://errors.authjs.dev#accessdenied

Using NextAuth V5 beta .20 so I didn't overwrite the /api/aut/callback/apple

@kamaladdi34
Copy link

@sl45sms thank you! that works just fine 👍

@larryhopecode
Copy link

Thanks to all for workarounds here. Just for reference, on latest beta 5.0.0-beta.20 thanks to @ChrGrb and #8428 there not need to override callback. In my case I decided not to try to get the name, and just allow user to change it. Here is my working configuration

export const authConfig = {
  cookies: {
    pkceCodeVerifier: {
      name: "next-auth.pkce.code_verifier",
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
     },
  },
  providers: [
    GitHub,
    Google,
    Apple({
      clientId: process.env.AUTH_APPLE_ID,
      clientSecret: ""+process.env.AUTH_APPLE_SECRET,
      checks: ["pkce"],
      token: {
        url: `https://appleid.apple.com/auth/token`,
      },
      client: {
        token_endpoint_auth_method: "client_secret_post",
      },
      authorization: {
        params: {
          response_mode: "form_post",
          response_type: "code",//do not set to "code id_token" as it will not work
          scope: "name email"
        },},
        profile(profile) {
          return {
            id: profile.sub,
            name: "Person Doe",//profile.name.givenName + " " + profile.name.familyName, but apple does not return name...
            email: profile.email,
            image: "",
          }
        }
    }),
}

Got a new type of error in /api/aut/callback/apple

AccessDenied: AccessDenied. Read more at https://errors.authjs.dev#accessdenied

Using NextAuth V5 beta .20 so I didn't overwrite the /api/aut/callback/apple

Found the issue and fixed. It is not related to Apple provider directly. It is related to email and id pass back process.

@nishu-murmu
Copy link

I'm using this config.
it is throwing nf: no authorization code in "callbackParameters"
here's the reference ss

Can anyone assist me on this?

import NextAuth from 'next-auth';
import CredentialProvider from 'next-auth/providers/credentials';
import Apple from 'next-auth/providers/apple';
import { apiRoutes, config } from './config';
import { Get, Post } from './services/api-service';
// import { userExists } from './services/apis/auth-api';

export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  providers: [
    Apple({
      clientId: process.env.AUTH_APPLE_ID,
      clientSecret: '' + process.env.AUTH_APPLE_SECRET,
      checks: ['pkce'],
      token: {
        url: `https://appleid.apple.com/auth/token`,
      },
      client: {
        token_endpoint_auth_method: 'client_secret_post',
      },
      authorization: {
        params: {
          response_mode: 'form_post',
          response_type: 'code', //do not set to "code id_token" as it will not work
          scope: 'name email',
        },
      },
      profile(profile) {
        console.log('🚀 ~ profile ~ profile:', profile);
        return {
          id: profile.sub,
          name: 'Person Doe', //profile.name.givenName + " " + profile.name.familyName, but apple does not return name...
          email: profile.email,
          image: '',
        };
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user, trigger }) {
      if (user) {
        token.userInfo = user;
      }
      if (trigger === 'update') {
        const userMetaInfo = await Get({
          path: apiRoutes.getUserDetails,
          // @ts-ignore
          headers: { Authorization: `Bearer ${token?.userInfo?.token?.data as string}` },
        });
        const userInfo = await Get({
          path: apiRoutes.getUserInfo,
          // @ts-ignore
          headers: { Authorization: `Bearer ${token?.userInfo?.token?.data}` },
        });
        token.userInfo = {
          // @ts-ignore
          ...token.userInfo,
          ...userInfo,
          meta: userMetaInfo,
        };
      }
      return token;
    },

    async session({ session, newSession, token }) {
      if (token?.sub && token?.userInfo) {
        // @ts-ignore
        session.user = token?.userInfo;
      }
      return session;
    },
  },
  session: { strategy: 'jwt' },
  trustHost: true,
  cookies: {
    sessionToken: {
      name: config.NEXT_AUTH_COOKIE_NAME,
      options: {
        httpOnly: false,
        sameSite: 'lax',
        path: '/',
        secure: true,
      },
    },
    pkceCodeVerifier: {
      name: 'next-auth.pkce.code_verifier',
      options: {
        httpOnly: true,
        sameSite: 'none',
        path: '/',
        secure: true,
      },
    },
  },
});

@glencoden
Copy link

Thanks to all for workarounds here. Just for reference, on latest beta 5.0.0-beta.20 thanks to @ChrGrb and #8428 there not need to override callback. In my case I decided not to try to get the name, and just allow user to change it. Here is my working configuration

export const authConfig = {
  cookies: {
    pkceCodeVerifier: {
      name: "next-auth.pkce.code_verifier",
      options: {
        httpOnly: true,
        sameSite: "none",
        path: "/",
        secure: true,
      },
     },
  },
  providers: [
    GitHub,
    Google,
    Apple({
      clientId: process.env.AUTH_APPLE_ID,
      clientSecret: ""+process.env.AUTH_APPLE_SECRET,
      checks: ["pkce"],
      token: {
        url: `https://appleid.apple.com/auth/token`,
      },
      client: {
        token_endpoint_auth_method: "client_secret_post",
      },
      authorization: {
        params: {
          response_mode: "form_post",
          response_type: "code",//do not set to "code id_token" as it will not work
          scope: "name email"
        },},
        profile(profile) {
          return {
            id: profile.sub,
            name: "Person Doe",//profile.name.givenName + " " + profile.name.familyName, but apple does not return name...
            email: profile.email,
            image: "",
          }
        }
    }),
}

I get the 'no authorization code in "callbackParameters"' error mentioned above with this setup (which seems to be working for some people?)

@JamesWalkerGit
Copy link

I get the 'no authorization code in "callbackParameters"' error mentioned above with this setup (which seems to be working for some people?)

I'm getting the same error on 5.0.0-beta.20 for Apple login

I know that the redirect URL is set to https://siteenv.mysiteurl.com/api/auth/callback/apple

Because I can see that url flash in the navigation bar before the error is thrown and the browser is redirected to

https://siteenv.mysiteurl.com/api/auth/error?error=Configuration

image

This is my auth.ts file copied the Apple section from the workarounds posted above.

import NextAuth from "next-auth"
import Apple from "next-auth/providers/apple"
import GitHub from "next-auth/providers/github"
import Google from "next-auth/providers/google"

export const { handlers, signIn, signOut, auth } = NextAuth({
    cookies: {
        pkceCodeVerifier: {
            name: "next-auth.pkce.code_verifier",
            options: {
                httpOnly: true,
                sameSite: "none",
                path: "/",
                secure: true,
            },
        },
    },
    providers: [GitHub, Google, Apple({
        clientId: process.env.AUTH_APPLE_ID,
        clientSecret: "" + process.env.AUTH_APPLE_SECRET,
        checks: ["pkce"],
        token: {
            url: `https://appleid.apple.com/auth/token`,
        },
        client: {
            token_endpoint_auth_method: "client_secret_post",
        },
        authorization: {
            params: {
                response_mode: "form_post",
                response_type: "code",//do not set to "code id_token" as it will not work
                scope: "name email"
            },
        }
    }),]
})

Google and Github logins work great tho 😂

If anyone can offer any help on this issue it'd be much appreciated, I might need to switch to a different auth library if Apple auth simply doesn't work with AuthJS.

@maiconcarraro
Copy link

@JamesWalkerGit you should try @ChrGrb solution #6788 (comment) thats what worked for me.

@JamesWalkerGit
Copy link

JamesWalkerGit commented Sep 23, 2024

@JamesWalkerGit you should try @ChrGrb solution #6788 (comment) thats what worked for me.

Hey thanks for the tip @maiconcarraro, I setup my auth.ts to mirror @ChrGrb 's config as far as I can tell, I successfully get thru the apple login and password authentication, and then when I am redirected back to the callback url on my end unfortunately I get these errors:

�[31m[auth][cause]�[0m: Error: TODO: Handle OIDC response body error
    "next": "^14.0.4",
    "next-auth": "5.0.0-beta.20",
image

auth.ts


import NextAuth from "next-auth"
import Apple from "next-auth/providers/apple"
import GitHub from "next-auth/providers/github"
import Google from "next-auth/providers/google"

export const { handlers, signIn, signOut, auth } = NextAuth({
    cookies: {
        pkceCodeVerifier: {
            name: "next-auth.pkce.code_verifier",
            options: {
                httpOnly: true,
                sameSite: "none",
                path: "/",
                secure: true,
            },
        },
    },
    secret: process.env.AUTH_SECRET,
    providers: [GitHub, Google, Apple({
        clientId: process.env.AUTH_APPLE_ID,
        // @ts-ignore
        clientSecret: process.env.AUTH_APPLE_SECRET,
        wellKnown: "https://appleid.apple.com/.well-known/openid-configuration",
        checks: ["pkce"],
        token: {
            url: `https://appleid.apple.com/auth/token`,
        },
        authorization: {
            url: 'https://appleid.apple.com/auth/authorize',
            params: {
                scope: '',
                response_type: 'code',
                response_mode: 'query',
                state: crypto.randomUUID()
            },
        },
        client: {
            token_endpoint_auth_method: "client_secret_post",
        },
    }),]
})

@maiconcarraro
Copy link

maiconcarraro commented Sep 23, 2024

@JamesWalkerGit the next-auth prefix for cookies won't work for the new v5 beta, it must be authjs, see source code here:

I'm using:

  const cookiePrefix = useSecureCookies ? "__Secure-" : "";

  ...
  return {
    ...
    pkceCodeVerifier: {
      name: `${cookiePrefix}authjs.pkce.code_verifier`,
      options: {
        httpOnly: true,
        sameSite: "lax",
        path: "/",
        secure: useSecureCookies,
        maxAge: COOKIES_LIFE_TIME,
      },
    },

and sameSite lax worked for me, you might try both, lax should be securer.

@JamesWalkerGit
Copy link

JamesWalkerGit commented Oct 1, 2024

Thanks for the heads up @maiconcarraro I tried that but unfortunately it seems I get the same errors.

Here is a link to a deployed repository that is a nextjs boilerplate from Vercel with implemented AuthJS following the documentation and then with the workaround suggested here for Apple login.

Deployed Site
Repository

Github login works ✅, Apple login does not ❌.


Default Setup following documentation - [31m[auth][cause]�[0m: TypeError: TODO: Authorization server did not provide a userinfo endpoint.
at (node_modules/@auth/core/lib/actions/callback/oauth/callback.js?12f8:29:0)

Pasted Graphic 1 Pasted Graphic 2

After Workaround - [31m[auth][cause]�[0m: Error: TODO: Handle OIDC response body error

auth.ts - with workaround

image Pasted Graphic 4

Hopefully a reproducible link to a boilerplate project helps?

Not sure where to go from here as I'm not sure if it's still something I'm doing wrong or if it's a bug that won't work no matter what I try here.

@maiconcarraro
Copy link

@JamesWalkerGit comparing to my project the differences are:

  • Not using edge runtime (I don't think its the cause, but sharing)
  • I have the full cookies specification not only pkce, all based on here:
    return {
    // default cookie options
    sessionToken: {
    name: `${cookiePrefix}authjs.session-token`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    },
    },
    callbackUrl: {
    name: `${cookiePrefix}authjs.callback-url`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    },
    },
    csrfToken: {
    // Default to __Host- for CSRF token for additional protection if using useSecureCookies
    // NB: The `__Host-` prefix is stricter than the `__Secure-` prefix.
    name: `${useSecureCookies ? "__Host-" : ""}authjs.csrf-token`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    },
    },
    pkceCodeVerifier: {
    name: `${cookiePrefix}authjs.pkce.code_verifier`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    maxAge: 60 * 15, // 15 minutes in seconds
    },
    },
    state: {
    name: `${cookiePrefix}authjs.state`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    maxAge: 60 * 15, // 15 minutes in seconds
    },
    },
    nonce: {
    name: `${cookiePrefix}authjs.nonce`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    },
    },
    webauthnChallenge: {
    name: `${cookiePrefix}authjs.challenge`,
    options: {
    httpOnly: true,
    sameSite: "lax",
    path: "/",
    secure: useSecureCookies,
    maxAge: 60 * 15, // 15 minutes in seconds
    },
    },
    } as const satisfies CookiesOptions

@JamesWalkerGit
Copy link

JamesWalkerGit commented Oct 2, 2024

@maiconcarraro Removed the edge runtime and added the full cookie spec based on that link, but unfortunately still seeing the same errors. 🫡

Github login works ✅, Apple login does not ❌.

auth.ts - with workaround and full cookie spec
Deployed Site
Repository

[31m[auth][cause]�[0m: Error: TODO: Handle OIDC response body error
at iq (/var/task/.next/server/app/api/auth/[...nextauth]/route.js:377:31528)
image

image

@earthpfasoo
Copy link

I tried @sl45sms's solution with NextAuth v5 beta 20, but I am facing this issue:
InvalidCheck: state value could not be parsed.
Has anybody solved this issue?

[auth][error] InvalidCheck: state value could not be parsed. Read more at https://errors.authjs.dev/#invalidcheck at iM (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:25934) at Object.use (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:26342) at iX (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:28282) at i7 (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:36910) at oc (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:48659) at async oh (/app/dist/server/app/api/auth/[...nextauth]/route.js:368:52984) at async /app/nodemodules/.pnpm/[email protected]@[email protected]@[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:36957 at async eC.execute (/app/node_modules/.pnpm/[email protected]@[email protected]@[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:27552) at async eC.handle (/app/node_modules/.pnpm/[email protected]@[email protected]@[email protected][email protected][email protected]/node_modules/next/dist/compiled/next-server/app-route.runtime.prod.js:6:38291) at async doRender (/app/node_modules/.pnpm/[email protected]@[email protected][email protected][email protected][email protected][email protected]/node_modules/next/dist/server/base-server.js:1352:42)

@Saran33
Copy link

Saran33 commented Nov 21, 2024

Thanks for this fix @balazsorban44 , no more workarounds needed for me anymore as of next-auth 5.0.0-beta.25👏❤️

The only minor issue, as mentioned in the comments of that commit, is that redirect proxies for response_mode=form_post aren't supported

@danielpl10
Copy link

danielpl10 commented Nov 25, 2024

Thanks all for the hard work, and feedback, I know this is closed, but is not clear what is the final solution, I'm still having the error id_token not present in token set, and with all these comments the final solution is not clear. I'm using next-auth v4 and prisma adapter, all the others providers works, except apple, even in the next-auth example webpage, apple login doesn't work. Sorry I'm confused, does apple provider works on v4 or only on v5? What is the final auth config code?, is supposed to be working with the defaults configuration but it doesn't. Thanks in advanced, please, help, is been a week trying this to work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working providers upstream The issue dervies from one of next-auth dependencies
Projects
None yet
Development

Successfully merging a pull request may close this issue.