atinux / nuxt-auth-utils

Add Authentication to Nuxt applications with secured & sealed cookies sessions.
MIT License
981 stars 91 forks source link

Microsoft OAuth Question about Access Token #67

Closed OliverMartini closed 8 months ago

OliverMartini commented 8 months ago

@jfrelik ; thanks for the Microsoft provider. Works great to authenticate against MS Graph.

How do you use it to authenticate against your own API Application? I am stuck, as when I add the access_as_user scope in the microsoftEventHandler config section.

scope: ['api://{my_application}/access_as_user','openid','offline_access', 'profile','User.Read',], // USE AN ARRAY FOR YOUR SCOPES this will allow me to call my own API, as only access_as_user will be included in scp of the access_token.

scope: ['openid','offline_access', 'profile','User.Read','api://{my_application}/access_as_user',], // USE AN ARRAY FOR YOUR SCOPES this will log-me in correctly and allow me to call the grap, as all but the access_as_user scp is in the access token.

Do I need two access tokens? One to access the Graph, and one for my API?

OliverMartini commented 8 months ago

I think I answered my own question...

For now, I solved by using @azure/msal library to get an apiAccessToken in the server/routes/auth/microsoft.get.ts call

import * as msal from '@azure/msal-node'

async function acquireAPITokenByRefreshToken(refreshToken) {
  const authority = `https://login.microsoftonline.com/${process.env.NUXT_OAUTH_MICROSOFT_TENANT}`
  const config = {
    auth: {
      clientId: process.env.NUXT_OAUTH_MICROSOFT_CLIENT_ID || '',
      authority,
      clientSecret: process.env.NUXT_OAUTH_MICROSOFT_CLIENT_SECRET || '',
      knownAuthorities: [authority],
    },
    system: {
      loggerOptions: {
        loggerCallback(loglevel, message, containsPii) {
          console.log(message)
        },
        piiLoggingEnabled: false,
        logLevel: msal.LogLevel.Error,
      },
    },
  }
  const cca = new msal.ConfidentialClientApplication(config)

  return cca.acquireTokenByRefreshToken({
    scopes: [`api://${process.env.NUXT_OAUTH_MICROSOFT_CLIENT_ID}/access_as_user`],
    refreshToken,
  }).catch((err) => console.log(err))
}

export default oauth.microsoftEventHandler({
  config: {
    scope: ['openid', 'offline_access', 'profile', 'User.Read',], // USE AN ARRAY FOR YOUR SCOPES
  },
  async onSuccess(event, { user, tokens }) {
    const apiAccessDetails = await acquireAPITokenByRefreshToken(tokens.refresh_token)
    await setUserSession(event, {
      user,
      loggedInAt: Date.now(),
      graphAccessToken: tokens.access_token,
      apiAccessToken: apiAccessDetails?.accessToken
    })
    console.log('User logged in')

    return sendRedirect(event, '/')
  }
})

Any suggestion how to implement cleaner would be appreciated.

atinux commented 8 months ago

Your solution looks good to me.