Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Accessing the access token from loader/action #20

Open
flexwie opened this issue Apr 11, 2023 · 3 comments
Open

Accessing the access token from loader/action #20

flexwie opened this issue Apr 11, 2023 · 3 comments

Comments

@flexwie
Copy link

flexwie commented Apr 11, 2023

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?

@franklinjavier
Copy link

franklinjavier commented May 8, 2023

@flexwie you can see a practical example here
#1

@flexwie
Copy link
Author

flexwie commented May 14, 2023

That would mean that I have to store it somewhere myself when authenticating a user, right?

@franklinjavier
Copy link

franklinjavier commented May 16, 2023

@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)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants