-
Notifications
You must be signed in to change notification settings - Fork 4k
Description
Summary of proposed feature
Introducing a new way of configuring OAuth providers. With this proposal, we can provide granular control from basic (with the best defaults we can think of) to completely controlled hooks into the login flow. (The user would be able to do the actual fetch calls themselves. Hopefully, this will almost never would be necessary)
Here is an example:
export default function Auth0(options) {
return {
id: "auth0",
name: "Auth0",
authorization: `https://${options.domain}/authorize?grant_type=authorization_code&response_type=code&scope=openid%20email%20profile`,
// Alternatively, you could pass an url and params
// which will be combined for you for convinience.
// authorization: {
// url: `https://${options.domain}/authorize`,
// params: {
// grant_type: "authorization_code",
// response_type: "code",
// scope: "openid email profile",
// },
// },
// Skips fetching user data. In some rare situations, you may not need this. See #1065
userinfo: null,
token: {
url: `https://${options.domain}/oauth/token`,
method: "POST",
via: "header",
// Complete control over how to get the userinfo.
async request({ tokens }) {
const response = await fetch("custom/endpoint/token", {
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
})
return await response.json()
},
},
profile(profile) {
return {
id: profile.sub,
name: profile.nickname,
email: profile.email,
image: profile.picture,
}
},
...options,
}
}Purpose of proposed feature
To simplify the configuration by reducing the number of required fields, but give full control at the same time, for advanced use cases.
Detail about proposed feature
So to sum it up, 3 new methods could be introduced, using a similar shape:
/** Any contextual information that makes the request useful, eg.: tokens in case of the token endpoint */
type RequestContext = any
type OAuthEndpoint = string | null | {
url?: string
method?: "POST" | "GET"
/** How to pass the access token */
via?: "header" | "body" | "query"
/** Will be used as URL params if method is GET, or the body as x-url-form-encoded if POST*/
params?: URLSearchParams | Record<string, unknown>
request(context: RequestContext)?: Promise<any>
}Potential problems
As there are no conflicting configuration options, this could be implemented in a non-breaking way, meaning in theory we don't have to wait until the next major version.
Describe any alternatives you've considered
The current configuration is fragile since the OAuth spec can be interpreted differently, which often ends up with slightly too specific implementations, which has been hard to handle until now. The best solution was one-off configuration flags for certain providers, but in the long term, it introduced bloat in the code.
Additional context
Please indicate if you are willing and able to help implement the proposed feature.
Could fit neatly into #1698, or a follow-up PR.
Related: #1065, #1642, #1605, #1607, #1756, #950
Please share your opinions!