providers/fusionauth
FusionAuthProfile
This is the default openid signature returned from FusionAuth it can be customized using lambda functions
Extends
Record
<string
,any
>
Indexable
[key
: string
]: any
Properties
at_hash
at_hash: string;
aud
aud: string;
authenticationType
authenticationType: string;
c_hash
c_hash: string;
email: string;
email_verified
email_verified: boolean;
exp
exp: number;
family_name?
optional family_name: string;
given_name?
optional given_name: string;
iat
iat: number;
iss
iss: string;
jti
jti: string;
middle_name?
optional middle_name: string;
name?
optional name: string;
picture?
optional picture: string;
preferred_username?
optional preferred_username: string;
scope
scope: string;
sid
sid: string;
sub
sub: string;
default()
function default<P>(options): OAuthConfig<P>
Add FusionAuth login to your page.
Setup
Callback URL
https://example.com/api/auth/callback/fusionauth
Configuration
import { Auth } from "@auth/core"
import FusionAuth from "@auth/core/providers/fusionauth"
const request = new Request(origin)
const response = await Auth(request, {
providers: [
FusionAuth({
clientId: FUSIONAUTH_CLIENT_ID,
clientSecret: FUSIONAUTH_CLIENT_SECRET,
tenantId: FUSIONAUTH_TENANT_ID,
issuer: FUSIONAUTH_ISSUER,
}),
],
})
If you’re using multi-tenancy, you need to pass in the tenantId option to apply the proper theme.
Resources
Notes
By default, Auth.js assumes that the FusionAuth provider is based on the OAuth 2 specification.
Configuration
An application can be created at https://your-fusionauth-server-url/admin/application.
For more information, follow the FusionAuth 5-minute setup guide.
In the OAuth settings for your application, configure the following.
- Redirect URL
- Enabled grants
- Make sure Authorization Code is enabled.
If using JSON Web Tokens, you need to make sure the signing algorithm is RS256, you can create an RS256 key pair by going to Settings, Key Master, generate RSA and choosing SHA-256 as algorithm. After that, go to the JWT settings of your application and select this key as Access Token signing key and Id Token signing key.
The FusionAuth provider comes with a default configuration. To override the defaults for your use case, check out customizing a built-in OAuth provider.
Disclaimer If you think you found a bug in the default configuration, you can open an issue.
Auth.js strictly adheres to the specification and it cannot take responsibility for any deviation from the spec by the provider. You can open an issue, but if the problem is non-compliance with the spec, we might not pursue a resolution. You can ask for more help in Discussions.
It is highly recommended to follow this example call when using the provider in Next.js so that you can access both the access_token and id_token on the server.
/// <reference types="next-auth" />
import NextAuth from 'next-auth';
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
{
id: 'fusionauth',
name: 'FusionAuth',
type: 'oidc',
issuer: process.env.AUTH_FUSIONAUTH_ISSUER!,
clientId: process.env.AUTH_FUSIONAUTH_CLIENT_ID!,
clientSecret: process.env.AUTH_FUSIONAUTH_CLIENT_SECRET!,
authorization: {
params: {
scope: 'offline_access email openid profile',
tenantId: process.env.AUTH_FUSIONAUTH_TENANT_ID!,
},
},
userinfo: `${process.env.AUTH_FUSIONAUTH_ISSUER}/oauth2/userinfo`,
// This is due to a known processing issue
// TODO: https://github.com/nextauthjs/next-auth/issues/8745#issuecomment-1907799026
token: {
url: `${process.env.AUTH_FUSIONAUTH_ISSUER}/oauth2/token`,
conform: async (response: Response) => {
if (response.status === 401) return response;
const newHeaders = Array.from(response.headers.entries())
.filter(([key]) => key.toLowerCase() !== 'www-authenticate')
.reduce(
(headers, [key, value]) => (headers.append(key, value), headers),
new Headers()
);
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders,
});
},
},
},
],
session: {
strategy: 'jwt',
},
// Required to get the account object in the session and enable
// the ability to call API's externally that rely on JWT tokens.
callbacks: {
async jwt(params) {
const { token, user, account } = params;
if (account) {
// First-time login, save the `access_token`, its expiry and the `refresh_token`
return {
...token,
...account,
};
} else if (
token.expires_at &&
Date.now() < (token.expires_at as number) * 1000
) {
// Subsequent logins, but the `access_token` is still valid
return token;
} else {
// Subsequent logins, but the `access_token` has expired, try to refresh it
if (!token.refresh_token) throw new TypeError('Missing refresh_token');
try {
const refreshResponse = await fetch(
`${process.env.AUTH_FUSIONAUTH_ISSUER}/oauth2/token`,
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
client_id: process.env.AUTH_FUSIONAUTH_CLIENT_ID!,
client_secret: process.env.AUTH_FUSIONAUTH_CLIENT_SECRET!,
grant_type: 'refresh_token',
refresh_token: token.refresh_token as string,
}),
}
);
if (!refreshResponse.ok) {
throw new Error('Failed to refresh token');
}
const tokensOrError = await refreshResponse.json();
if (!refreshResponse.ok) throw tokensOrError;
const newTokens = tokensOrError as {
access_token: string;
expires_in: number;
refresh_token?: string;
};
return {
...token,
access_token: newTokens.access_token,
expires_at: Math.floor(Date.now() / 1000 + newTokens.expires_in),
// Some providers only issue refresh tokens once, so preserve if we did not get a new one
refresh_token: newTokens.refresh_token
? newTokens.refresh_token
: token.refresh_token,
};
} catch (error) {
console.error('Error refreshing access_token', error);
// If we fail to refresh the token, return an error so we can handle it on the page
token.error = 'RefreshTokenError';
return token;
}
}
},
async session(params) {
const { session, token } = params;
return { ...session, ...token };
},
},
});
declare module 'next-auth' {
interface Session {
access_token: string;
expires_in: number;
id_token?: string;
expires_at: number;
refresh_token?: string;
refresh_token_id?: string;
error?: 'RefreshTokenError';
scope: string;
token_type: string;
userId: string;
provider: string;
type: string;
providerAccountId: string;
}
}
declare module 'next-auth' {
interface JWT {
access_token: string;
expires_in: number;
id_token?: string;
expires_at: number;
refresh_token?: string;
refresh_token_id?: string;
error?: 'RefreshTokenError';
scope: string;
token_type: string;
userId: string;
provider: string;
type: string;
providerAccountId: string;
}
}
Type Parameters
Type Parameter |
---|
P extends FusionAuthProfile |
Parameters
Parameter | Type |
---|---|
options | OAuthUserConfig <P > & { tenantId : string ; } |
Returns
OAuthConfig
<P
>