Feat/SW-3461 setup auth with sas eurobonus * feat(SW-3461): Setup auth for sas eurobonus * . * feat: setup auth towards SAS * Fix auth via SAS and add logout route * . * merge * auth via SAS * fix powered by scandic logo * Merge branch 'master' of bitbucket.org:scandic-swap/web into feat/SW-3461-setup-auth-with-sas-eurobonus * Include access_token in jwt after successful login * merge Approved-by: Anton Gunnarsson
128 lines
3.2 KiB
TypeScript
128 lines
3.2 KiB
TypeScript
import NextAuth, { type NextAuthConfig } from "next-auth"
|
|
import Auth0Provider from "next-auth/providers/auth0"
|
|
|
|
import { createLogger } from "@scandic-hotels/common/logger/createLogger"
|
|
|
|
import { env } from "@/env/server"
|
|
|
|
const authLogger = createLogger("auth")
|
|
/*
|
|
TODO: Get info for SAS token timeout and accordingly adjust pre-refresh time move to common/contants
|
|
Do we need to handle refresh tokens at all, isn't that handled by the Auth0 provider?
|
|
Needs to be verified
|
|
*/
|
|
|
|
const sasProvider = Auth0Provider({
|
|
id: "sas",
|
|
name: "SAS",
|
|
clientId: env.SAS_AUTH_CLIENTID,
|
|
issuer: env.SAS_AUTH_ENDPOINT,
|
|
checks: ["state"],
|
|
authorization: {
|
|
params: {
|
|
audience: "eb-partner-api",
|
|
},
|
|
},
|
|
client: {
|
|
token_endpoint_auth_method: "none",
|
|
},
|
|
})
|
|
|
|
const config: NextAuthConfig = {
|
|
basePath: "/api/web/auth",
|
|
providers: [sasProvider],
|
|
session: {
|
|
strategy: "jwt",
|
|
},
|
|
cookies: {
|
|
sessionToken: {
|
|
name: "sas-session",
|
|
},
|
|
},
|
|
callbacks: {
|
|
async signIn() {
|
|
return true
|
|
},
|
|
async jwt(params) {
|
|
if (params.trigger === "signIn") {
|
|
const accessToken = params.account?.access_token
|
|
const expiresAt = params.account?.expires_at
|
|
|
|
if (!accessToken) {
|
|
throw new Error("AuthError: Missing access token")
|
|
}
|
|
|
|
if (!expiresAt) {
|
|
throw new Error("AuthError: Missing expiry time")
|
|
}
|
|
|
|
return {
|
|
...params.token,
|
|
loginType: "sas",
|
|
access_token: accessToken,
|
|
expires_at: expiresAt,
|
|
}
|
|
}
|
|
|
|
return params.token
|
|
},
|
|
async session({ session, token }) {
|
|
return {
|
|
...session,
|
|
error: token.error,
|
|
user: session.user
|
|
? {
|
|
...session.user,
|
|
id: token.sub,
|
|
}
|
|
: undefined,
|
|
token: {
|
|
access_token: token.access_token,
|
|
expires_at: token.expires_at,
|
|
error: token.error,
|
|
},
|
|
}
|
|
},
|
|
async redirect({ baseUrl, url }) {
|
|
authLogger.debug(`[auth] deciding redirect URL`, { baseUrl, url })
|
|
if (url.startsWith("/")) {
|
|
authLogger.debug(
|
|
`[auth] relative URL accepted, returning: ${baseUrl}${url}`
|
|
)
|
|
// Allows relative callback URLs
|
|
return `${baseUrl}${url}`
|
|
} else {
|
|
// Assume absolute URL
|
|
try {
|
|
const parsedUrl = new URL(url)
|
|
if (/\.scandichotels\.com$/.test(parsedUrl.hostname)) {
|
|
authLogger.debug(`[auth] subdomain URL accepted, returning: ${url}`)
|
|
// Allows any subdomains on all top level domains above
|
|
return url
|
|
} else if (parsedUrl.origin === baseUrl) {
|
|
// Allows callback URLs on the same origin
|
|
authLogger.debug(`[auth] origin URL accepted, returning: ${url}`)
|
|
return url
|
|
}
|
|
} catch (e) {
|
|
authLogger.error(
|
|
`[auth] error parsing incoming URL for redirection`,
|
|
e
|
|
)
|
|
}
|
|
}
|
|
authLogger.debug(`[auth] URL denied, returning base URL: ${baseUrl}`)
|
|
|
|
return baseUrl
|
|
},
|
|
},
|
|
}
|
|
|
|
export const {
|
|
handlers: { GET, POST },
|
|
signIn,
|
|
signOut,
|
|
} = NextAuth(config)
|
|
|
|
export const { auth } = NextAuth(config)
|