next-auth
next-auth copied to clipboard
callbackUrl not working when signIn with apple
Description 🐜
When I sign in with apple or google I want to navigate back to current page (the page when click sigin button). It's work with google and but when I sign in with apple, it's always navigate to home page.
Hope that everyone can help me fix this bug. Thank you so much.
How to reproduce ☕️
Here is the next-auth config
And the function handle signin.
Environment 🖥
"next-auth": "^3.25.0", "next": "^10.2.0",
System: OS: macOS 11.4 CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz Memory: 363.25 MB / 16.00 GB Shell: 5.8 - /bin/zsh Binaries: Node: 14.15.0 - ~/.nvm/versions/node/v14.15.0/bin/node Yarn: 1.22.10 - /usr/local/bin/yarn npm: 6.14.8 - ~/.nvm/versions/node/v14.15.0/bin/npm Watchman: 4.9.0 - /usr/local/bin/watchman Browsers: Chrome: 91.0.4472.77 Safari: 14.1.1
You don't need to define the callbackUrl
if you only want to return to the same page, it's the default behaviour already. It sounds strange though that it works for one provider but not the other.
I'm wondering if this section is relevant, have you seen it?: https://next-auth.js.org/providers/apple#testing
Aside from that, any good reason for using useSecureCookies: false
? Hope it's not in production, because it is a security risk. I would also not expose the idToken
to the client through the session callback like that. Curious what you are trying to achieve with it. 🤔
@balazsorban44 About useSecureCookies, I use it for testing only. I've checked the logs in callbacks: redirect function. The current url still be keep when we navigate from webpage to apple authorize page. But when we navigate back to webpage it auto reset to root url.
@balazsorban44 I think it related to this lines. Because I see that the callback cookies has reset to baseUrl when navigating from apple authorize page to my website.
https://github.com/nextauthjs/next-auth/blob/71f63117a9576d22f8958c6ee9492a09e21b39a6/src/server/lib/callback-url-handler.js#L27-L30
I had similar issues with azureb2c, this might offer a temporary alternative for testing until issue is fixed 👇🏾
https://github.com/nextauthjs/next-auth/issues/1542#issuecomment-812409291
I also have the same issue with apple login.
I have the same login flow with facebook , google , which run ok but only apple doesn't..
I was able to fix the issue in azureb2c by adjusting the response_mode value in the AuthorizationUrl from form_post to query
Examples :
authorizationUrl: https://${tenantName}.b2clogin.com/${tenantName}.onmicrosoft.com/${loginFlow}/oauth2/v2.0/authorize?response_type=code+id_token+token&response_mode=query
,
Hope this helps
Thank you @innowhat for the workaround, worked fine with Apple. However setting the response_mode
to query
doesn't allow any scope to be used to retrieve user info, sadly (although at this time scopes are also broken for Apple login)
I'm experiencing this issue too.
@FernandVEYRIER @innowhat - How can I use your response_mode
workaround? Would I need to fork the repo and then edit packages/next-auth/src/providers/apple.ts?
Hi @KristenWilde, I have never used apple as a provider so cant really tell if the work around applies there as well. Anyways, you could try overriding your apple provider while using the 'query' response_mode, and if works then perhaps you could raise a PR for a fix.
Here is an example of how it could look like, hope this helps.
export default NextAuth({
providers: [
{
id: 'apple',
name: 'Apple',
type: 'oauth',
version: '2.0',
wellKnown: 'https://appleid.apple.com/.well-known/openid-configuration',
authorization: {
// note we use 'query' instead of 'form_post' here
params: { scope: 'name email', response_mode: 'query' },
},
checks: ['pkce'],
idToken: true,
profile(profile) {
...
}
},
options: {
clientId: '',
clientSecret: '',
/**
* Apple requires the client secret to be a JWT. You can generate one using the following script:
* https://bal.so/apple-gen-secret
*
* Read more: [Creating the Client Secret
](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048)
*/
},
},
],
...
})
Note: this only applies to next-auth4 or later
Hi @KristenWilde, I have never used apple as a provider so cant really tell if the work around applies there as well. Anyways, you could try overriding your apple provider while using the 'query' response_mode, and if works then perhaps you could raise a PR for a fix.
Here is an example of how it could look like, hope this helps.
export default NextAuth({ providers: [ { id: 'apple', name: 'Apple', type: 'oauth', version: '2.0', wellKnown: 'https://appleid.apple.com/.well-known/openid-configuration', authorization: { // note we use 'query' instead of 'form_post' here params: { scope: 'name email', response_mode: 'query' }, }, checks: ['pkce'], idToken: true, profile(profile) { ... } }, options: { clientId: '', clientSecret: '', /** * Apple requires the client secret to be a JWT. You can generate one using the following script: * https://bal.so/apple-gen-secret * * Read more: [Creating the Client Secret ](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens#3262048) */ }, }, ], ... })
Note: this only applies to next-auth4 or later
From my experience the scope
doesn't work when setting the response_mode
to query., and Apple denies the login. Removing the scope
parameter fixes the problem.
Thanks @FernandVEYRIER and @innowhat! I am using an older version of next-auth, but it was easy to change the response_mode
and remove the scope
in the Providers.Apple config.
Providers.Apple({
clientId: process.env.APPLE_ID,
clientSecret: { ... },
authorizationUrl:
'https://appleid.apple.com/auth/authorize?response_type=code&id_token&response_mode=query',
})
This worked for signing in and redirecting, but unfortunately my app doesn't work without the user's name and email.
We got the Apple redirect working by changing the cookie config for the callbackUrl. sameSite: 'lax'
was a problem so we added this to our config:
cookies: {
callbackUrl: {
name: `__Secure-next-auth.callback-url`,
options: {
httpOnly: false,
sameSite: 'none',
path: '/',
secure: true,
},
},
(still using next-auth version 3).
@KristenWilde Thank you!
I think this fixed the root cause of the issue: missing cookies on a request coming in from https://appleid.apple.com/ to /api/auth/callback/apple.
Before adding your cookie config to next-auth options, that request looked like this (no cookies):
referer: https://appleid.apple.com/
url: /api/auth/callback/apple
method: POST
cookies: {}
body: {
code: 'some-code-here'
}
and after (with callback-url cookie):
referer: https://appleid.apple.com/
url: /api/auth/callback/apple
method: POST
cookies: {
'__Secure-next-auth.callback-url': 'https://example.com/send-me-here
}
body: {
code: 'some-code-here'
}
This cookie value is then used as a redirect url, and user is successfully redirected to the path specified in signIn call:
signIn("apple", {
callbackUrl: "/send-me-here",
})
And this is how my NextAuthOptions looks like now:
export const authOptions: NextAuthOptions = {
cookies: {
callbackUrl: {
name: `__Secure-next-auth.callback-url`,
options: {
httpOnly: false,
sameSite: "none",
path: "/",
secure: true,
},
},
},
providers: [
Apple({
authorization: {
params: {
scope: "name email",
response_mode: "form_post",
response_type: "code",
},
},
clientId: process.env.APPLE_ID,
clientSecret: "some-secret-here",
}),
]
}
Before finding out this fix I was going to submit the pull request where I added callbackUrl in NextAuthOptions. Then this callbackUrl would be used instead of url.origin as fallback in case when there is no callbackUrl in cookies, body or query params in requests coming in to /api/auth/callback/
I tested locally. It seems using signIn
like this solves the problem. In your Apple Login Button onClick
onClick={() => {
signIn( 'apple',
{ callbackUrl: "https://<your-redirect-url>" },
{ redirect_uri: "https://<your-redirect-url>" });
}}
Edit: But not works if you don't apply api/auth/callback/apple
to end of your url, And with that, It does not working again.
Edit2: @senad87 's solution works perfect 👌 Thanks.