Open flexwie opened 1 year ago
@flexwie you can see a practical example here https://github.com/juhanakristian/remix-auth-microsoft/issues/1
That would mean that I have to store it somewhere myself when authenticating a user, right?
@flexwie In the Session/Cookie. eg:
// session.server.ts
import { createCookieSessionStorage, redirect } from '@remix-run/node'
import type { Session } from '@remix-run/node'
import type { UserProfile } from './auth.server'
import { LOGIN_URL } from '~/utils/constants'
// export the whole sessionStorage object
export const sessionStorage = createCookieSessionStorage({
cookie: {
name: 'eratus-session',
sameSite: 'lax', // this helps with CSRF
path: '/', // remember to add this so the cookie will work in all routes
httpOnly: true, // for security reasons, make this cookie http only
secrets: [process.env.SESSION_SECRET],
secure: process.env.NODE_ENV === 'production', // enable this in prod only
},
})
export const { commitSession, destroySession } = sessionStorage
export function getSession(request: Request): Promise<Session> {
return sessionStorage.getSession(request.headers.get('Cookie'))
}
export async function getSessionUser(request: Request) {
const session = await getSession(request)
return session.get('user') as UserProfile
}
export async function getLoggedInUser(request: Request) {
const user = await getSessionUser(request)
if (user) return user
throw needLogin(request)
}
export async function needLogin(request: Request) {
const { pathname, search } = new URL(request.url)
const session = await getSession(request)
session.set('redirect', `${pathname}${search}`)
return redirect(LOGIN_URL, {
headers: {
'Set-Cookie': await commitSession(session),
},
})
}
// auth.server.ts
import { Authenticator } from 'remix-auth'
import { MicrosoftStrategy } from 'remix-auth-microsoft'
import type { MicrosoftProfile } from 'remix-auth-microsoft'
import { getUser } from '~/models/user.server'
import { sessionStorage } from '~/services/session.server'
import { decodeToken } from '~/services/token.server'
export interface UserProfile extends MicrosoftProfile {
employeeId: number
isActive: boolean
roles: string[]
}
export const authenticator = new Authenticator<UserProfile>(sessionStorage)
const baseURL =
process.env.APP_URL ||
(process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : 'http://localhost:3000')
const microsoftStrategy = new MicrosoftStrategy(
{
clientId: process.env.MS_CLIENT_ID || '',
clientSecret: process.env.MS_CLIENT_SECRET || '',
redirectUri: `${baseURL}/auth/microsoft/callback`,
tenantId: process.env.MS_TENANT || '',
prompt: 'select_account',
},
async ({ extraParams, profile }) => {
const { id_token } = extraParams
const idToken = decodeToken(id_token)
const roles = idToken?.roles || []
const user = await getUser(profile._json.email)
return {
...profile,
employeeId: user.EmployeeId,
isActive: user.IsActive,
roles,
}
},
)
authenticator.use(microsoftStrategy)
I was wondering how I could access the access token from a loader or action function to call an upstream API. Do I have to add it to the session in the authenticator callback?