Re-enable ability for the token request to be overriden completely
☕️ Reasoning
When dealing with a custom oauth provider that has a non compliant token endpoint this functionality allows this library to be used. This functionality was present in v4 of the library.
In v5 this has been removed. A conform endpoint has been added for internal use to manipulate the response from token endpoints. However this does help if the request does not conform exactly to the standard.
As an example the company I work for requires some extra parameters to be sent in the token request (including the state parameter) Other than that the solution is oauth compliant. It would be a shame if we couldn't use v5 because of this restraint.
Another example I can see in the v5 branch is the tiktok provider which I assume is currently broken by its requirement to have a custom token request.
This PR implements the existing type contract that was carried over from the v4 branch but not implemented.
🧢 Checklist
- [ ] Documentation
- [ ] Tests
- [ ] Ready to be merged
🎫 Affected issues
There are quite a few issues and comments about not being able to control the request endpoint
https://github.com/nextauthjs/next-auth/issues/10852 https://github.com/nextauthjs/next-auth/issues/10732 https://github.com/nextauthjs/next-auth/discussions/10829
📌 Resources
The latest updates on your projects. Learn more about Vercel for Git ↗︎
| Name | Status | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| auth-docs | ❌ Failed (Inspect) | Jun 1, 2024 9:33pm |
1 Ignored Deployment
| Name | Status | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| next-auth-docs | ⬜️ Ignored (Inspect) | Visit Preview | Jun 1, 2024 9:33pm |
@PaulWild is attempting to deploy a commit to the authjs Team on Vercel.
A member of the Team first needs to authorize it.
Thanks for the reply, I completely understand the rational and from the discussions being had in the issues linked it is not unexpected.
From a selfish perspective I think my works provider wont change any time soon so if there is room for some customization of the code grant request that would be fantastic. I am more than happy to contribute towards a more acceptable solution if you have one in mind? Perhaps the ability to supply extra parameters to the request (with access to properties like state)? From a read of other issues this might solve issues faced by them.
@balazsorban44 We really need some way to override this token method.
We work with multiple vendors who are not going to change their non-conformant token APIs so we can use the latest version of Auth.js. This was not an issue with v4, but we are unable to use v5 with them as as we cannot override the token requests.
Indeed it would be valuable to override the default token.request. Below a use case that requires it, and for which the provider is within the OAuth 2.0 specification:
- Wordpress OAuth2 Authentication requires sending the client credentials (
client_idandclient_secret) in the request-body. - RFC 6749, section 2.3.1 mentions that this is allowed (even if not recommended).
- However, the default
token.requestbehavior only uses the Basic Authorization header scheme.
Note: The V5 next-auth WordpressProvider would anyways ignore a custom token.request because the merging approach for default and custom options is still in-progress. Although this is a different issue, I mention it here in case someone decides to test Wordpress OAuth using this built-in provider (use a custom one instead).
Same here with the tiktok provider, uses client_key and client_secret and for the token endpoint i need those body parameters to be passed as application/x-www-form-urlencoded (tiktok docs here) , in v4 that was no problem, since we could take control over the token request and is very unlikely that tiktok will change it standars anytime soon.
https://github.com/nextauthjs/next-auth/blob/e87a0b603e0fa38087bf230eb25fded77cce34d1/packages/core/src/providers/tiktok.ts#L214-L244
Maybe i'm missing something here, Is there a way to pass the body params of the token endpoint as application/x-www-form-urlencoded ?
+1 here (I work with Paul)
We'd like to use the latest NextAuth but can't without having this extra bit of control.
+1. A number of big providers don't comply with the spec, and there's not much you can do to make them comply. Breaking compatibility with them only hurts developers using your library.
There's ways to use the new conform function for the providers that do not comply with the spec, like tiktok for example, but it requires to make another or more requests after NextAuth tries its owns, here is a code reference
let tkCode: string | undefined;
let tkCallback: string | undefined;
export const { handlers, auth, signIn, signOut } = NextAuth(req =>{
if (req?.method === 'GET' && req?.headers.get('referer')?.includes('tiktok')) {
const url = new URL(req?.url);
tkCode = url.searchParams.get('code') as string;
tkCallback = url.pathname
}
return {
theme: { logo: "https://authjs.dev/img/logo-sm.png" },
adapter: UnstorageAdapter(storage),
providers: [
GitHub,
TikTok({
clientId: process.env.AUTH_TIKTOK_KEY,
clientSecret: process.env.AUTH_TIKTOK_SECRET,
token: {
async conform(response: Response) {
const res = await fetch(response.url, {
method: 'POST',
headers: {
'Cache-Control': 'no-cache',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_key: process.env.AUTH_TIKTOK_KEY!,
client_secret: process.env.AUTH_TIKTOK_SECRET!,
code: tkCode!,
grant_type: 'authorization_code',
redirect_uri: process.env.AUTH_URL! + tkCallback ,
}),
});
return res;
},
}
})
],
basePath: "/auth",
callbacks: {
authorized({ request, auth }) {
const { pathname } = request.nextUrl
if (pathname === "/middleware-example") return !!auth
return true
},
jwt({ token, trigger, session, account }) {
if (trigger === "update") token.name = session.user.name
if (account?.provider === "keycloak") {
return { ...token, accessToken: account.access_token }
}
return token
},
async session({ session, token }) {
if (token?.accessToken) {
session.accessToken = token.accessToken
}
return session
},
},
experimental: {
enableWebAuthn: true,
},
debug: process.env.NODE_ENV !== "production" ? true : false,
} satisfies NextAuthConfig
})
Oof! This is a classic case of "You're not in the business you think you're in, you're in the business your customers think you're in".
There's seemingly a mismatch of expectations here in that maintainers believe this to be an OAuth 2.0 and OIDC library, where as "customers" believe this is a general purpose auth library. I'd expect that perceptions to shift even further in the direction of "general purpose" auth library with the shift to auth.js (from next-auth) and the new website which doesn't even mention OAuth or OIDC anywhere on the landing or Getting Started pages.
Don't get me wrong, totally sympathize with the maintainers, but there's a plethora of issues and discussions popping up already about broken providers in v5; I suspect this is just the tip of the iceberg since v5 isn't released yet. Breaking providers is never ideal, but understandable given the major version bump. What's really problematic though is blocked providers — those who seemingly can no longer be supported at all. Solutions like the proposed hacky follow-up request (after a known failing request) called from conform for the official Tiktok provider (https://github.com/nextauthjs/next-auth/pull/11308) are far from ideal.
The underlying issue seems to be that all these providers are trying to shoehorn their non-compliant implementations into OAuthConfig<Profile> when they're not technically OIDC, or even in some cases valid OAuth2 flows. This leads me to believe that the abstractions in this library aren't quite right to cover the use-cases that the community is expecting.
A more robust solution would be to define a more formal event/callback driven Provider API, and then next-auth just provides a single concrete implementation that consumes the existing configs. Then truly custom providers would be possible without next-auth needing to explode in complexity to support all these weird edge cases of the various providers. Instead these providers can implement the API rather than trying to patch their wonky implementations into the standard implementation.
I closed this as the response was that this wasn't the approach that would be taken for this issue, which is totally understandable.
However there is enough discussion going on that I am going to reopen it, so it gets a bit more visibility to encourage said discussion .
Released a temporary package to add back this feature with latest release of package @auth/core:0.35.1:
https://www.npmjs.com/package/@emulienfou/auth-core
Thanks to @PaulWild
Seems we have a solution, haven't tested it out yet tho
#11975
Superseded by https://github.com/nextauthjs/next-auth/pull/11975
This adds the ability to override any of the requests now. Use it sparingly!
Example usage, to conform the Microsoft Entra ID provider that returns the wrong issuer: https://github.com/nextauthjs/next-auth/pull/11980
(As of writing, not yet out in next-auth beta, but all other @auth/* libs will already have it. NextAuth.js will follow soon.)