Step-by-Step Guide to using custom OAuth provider with SvelteKitAuth
Chapter 4 of Comprehensive Guide to SvelteKitAuth: Secure Authentication for SvelteKit Apps
In the previous article, we covered the integration of a built-in OAuth provider with SvelteKitAuth. In this article, we will delve into integrating a custom OAuth provider with SvelteKitAuth.
A custom provider can be particularly useful when (a) you require extensive customization in your authentication mechanism, or (b) the authentication provider you're using is not currently supported by Auth.js.
Here is the code snippet for the custom provider. Let us now deep dive into custom providers and the properties that are used within the provider.
// hooks.server.ts
import type { SvelteKitAuthConfig } from '@auth/sveltekit';
import { VERCEL_SECRET, CLIENT_ID, CLIENT_SECRET, ISSUER, WELL_KNOWN } from '$env/static/private';
const config: SvelteKitAuthConfig = {
providers: [{
id: 'auth0',
name: 'custom-oauth-provider',
type: 'oidc',
client: {
token_endpoint_auth_method: 'client_secret_post'
},
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
issuer: ISSUER,
wellKnown: WELL_KNOWN,
checks: ['pkce'],
authorization: {
url: `${ISSUER}authorize`, // 'http://localhost:4200/authorize
params: {
scope: 'openid name email profile',
redirect_uri: `${event.url.origin}/auth/callback/auth0`
}
},
token: `${ISSUER}oauth/token`,
userinfo: `${ISSUER}userinfo`
}],
secret: VERCEL_SECRET,
debug: true,
session: {
maxAge: 1800 // 30 mins
}
};
export const handle = SvelteKitAuth(config) satisfies Handle;
id,name,clientId,clientSecret,issuerandwellKnown- these configurations remain the same as they were discussed in the last section. The focus here will be on thetypeproperty. Thetypeproperty specifies the type of authentication mechanism, allowed values are: "oidc", "oauth", "credentials", and "email".If your provider is OpenID Connect (OIDC) compliant, the recommendation is to use the
wellKnownoption instead. OIDC usually returns anid_tokenfrom thetokenendpoint.SvelteKitAuthcan decode theid_tokento get the user information, instead of making an additional request to theuserinfoendpoint.In case your provider is not OIDC compliant, we have the option to customize the configuration by using a combination of the following properties. You can find more information in the docs.
authorization: This is the URL for authentication. There are two ways to use this option:
You can either set
authorizationto be a full URL, like"https://example.com/oauth/authorization?scope=email".Use an object with
urlandparamslike soauthorization: { url: "https://example.com/oauth/authorization", params: { scope: "email" } }
token: This is the URL that will fetch token information. There are three ways to use this option:
You can either set
tokento be a full URL, like"https://example.com/oauth/token?some=param".Use an object with
urlandparamslike sotoken: { url: "https://example.com/oauth/token", params: { some: "param" } }Completely take control of the request:
token: { url: "https://example.com/oauth/token", async conform(response) { if (response.ok) { const body = await response.clone().json() if (body?.response?.access_token) { return new Response(JSON.stringify(body.response), response) } else if (body?.access_token) { console.warn("Token response conforms to the standard, workaround not needed.") } } return response } }
userinfo: A
userinfoendpoint returns information about the logged-in user. It is not part of the OAuth specification but is usually available for most providers. There are three ways to use this option:You can either set
userinfoto be a full URL, like"https://example.com/oauth/userinfo?some=param".Use an object with
urlandparamslike souserinfo: { url: "https://example.com/oauth/userinfo", params: { some: "param" } }Completely take control of the request:
userinfo: { url: "https://example.com/oauth/userinfo", // The result of this method will be the input to the `profile` callback. async conform(response) { if (response.ok) { const body = await response.clone().json() if (body?.response?.access_token) { return new Response(JSON.stringify(body.response), response) } else if (body?.access_token) { console.warn("Token response conforms to the standard, workaround not needed.") } } return response } }
And that's it! We are ready with our custom OAuth Auth0 provider. Here is the final snippet that we will be using in the hooks.server.ts file:
import type { Handle } from '@sveltejs/kit';
import { SvelteKitAuth, type SvelteKitAuthConfig } from '@auth/sveltekit';
import { VERCEL_SECRET, CLIENT_ID, CLIENT_SECRET, ISSUER, WELL_KNOWN } from '$env/static/private';
const { handle: getAuthConfig } = SvelteKitAuth(async (event) => {
const config: SvelteKitAuthConfig = {
providers: [{
id: 'auth0',
name: 'custom-oauth-provider',
type: 'oidc',
client: {
token_endpoint_auth_method: 'client_secret_post'
},
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
issuer: ISSUER,
wellKnown: WELL_KNOWN,
checks: ['pkce'],
authorization: {
url: `${ISSUER}authorize`, // 'http://localhost:4200/authorize
params: {
scope: 'openid name email profile',
redirect_uri: `${event.url.origin}/auth/callback/auth0`
}
},
token: `${ISSUER}oauth/token`,
userinfo: `${ISSUER}userinfo`
}],
secret: VERCEL_SECRET,
debug: true,
trustHost: true,
session: {
strategy: 'jwt',
maxAge: 1800 // 30 mins
},
logger: {
error: async (error: any) => {
console.log('Error trace from SvelteKitAuth:', error);
}
}
};
return config;
});
export const handle = SvelteKitAuth(getAuthConfig) satisfies Handle;
In conclusion, integrating a custom OAuth provider with SvelteKitAuth offers flexibility and extensive customization options for your authentication mechanism. By understanding and configuring properties such as authorization, token, and userinfo, you can tailor the authentication process to meet your specific needs. Additionally, the ability to include multiple providers in the same configuration enhances the versatility of your application. With these steps, you are well-equipped to implement a robust and customized authentication system using SvelteKitAuth.
Here is the link to the GitHub repository with the codebase. In the next article, we will go through the steps on configuring multiple providers with SvelteKitAuth.