E_UNAUTHORIZED_ACCESS Error avec AdonisJs et Google oAuth

Nathalie099 Messages postés 11 Date d'inscription mardi 30 avril 2019 Statut Membre Dernière intervention 28 novembre 2024 - Modifié le 28 nov. 2024 à 18:09

J'ai créé un projet avec adonisJs. J'utilise google oAuth et les sessions pour gérer l'authentification. Lorsque je me connecte l'utilisateur est bien authentifié et inséré en base mais lorsque je lance un appel postman protégé par mon auth_middleware, la session est vide et j'obtiens cette erreur 401 E_UNAUTHORIZED_ACCESS. const isAuthenticated = await ctx.auth.check() est vide. Pourtant, je passe bien l'accessToken via postman. 

authRoutes :

const AuthController = () => import('#controllers/auth_controller')
import router from '@adonisjs/core/services/router'

export default function authRoutes() {
  router
    .group(() => {
      router.get('/login', [AuthController, 'login'])
      router.get('/callback', [AuthController, 'callback'])
    })
    .prefix('/auth/google')
}

auth_Controller :

import User from '#models/user'
import { HttpContext } from '@adonisjs/core/http'

export default class AuthController {
  async login({ ally }: HttpContext): Promise<any> {
    return ally.use('google').redirect()
  }

  async callback({ ally, session, auth, response }: HttpContext) {
    try {
      const googleUser = await ally.use('google').user()

      const user = await User.firstOrCreate(
        { googleId: googleUser.id },
        {
          email: googleUser.email,
          name: googleUser.name,
          avatar: googleUser.avatarUrl,
          accessToken: googleUser.token.idToken,
          refreshToken: googleUser.token.refreshToken,
        }
      )

      await auth.use('web').login(user)
      session.put('userId', user.id)

      session.flash('success', 'Connecter avec google')

      return response.redirect('/')
    } catch (error) {
      console.error('OAuth Error:', error)
    }
  }
}

auth_middleware :

import { Authenticators } from '@adonisjs/auth/types'
import { HttpContext } from '@adonisjs/core/http'
import { NextFn } from '@adonisjs/core/types/http'

export default class AuthMiddleware {
  /**
   * The URL to redirect to, when authentication fails
   */

  redirectTo = '/auth/google/login'

  async handle(
    ctx: HttpContext,
    next: NextFn,
    options: { guards?: (keyof Authenticators)[] } = {}
  ) {
    try {

      const guards = options.guards || ['web']

      // Authentification explicite
      await ctx.auth.authenticateUsing(guards, {
        loginRoute: this.redirectTo,
      })

      const isAuthenticated = await ctx.auth.check()

      if (!isAuthenticated) {
        return ctx.response.status(401).send('Unauthorized')
      }

      return next()
    } catch (error) {
      console.error('Authentication Error:', error)
      return ctx.response.redirect(this.redirectTo)
    }
  }
}
userModel : 

import { DateTime } from 'luxon'
import hash from '@adonisjs/core/services/hash'
import { compose } from '@adonisjs/core/helpers'
import { BaseModel, column, hasMany } from '@adonisjs/lucid/orm'
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
import { DbAccessTokensProvider } from '@adonisjs/auth/access_tokens'
import Rooms from './rooms.js'
import type { HasMany } from '@adonisjs/lucid/types/relations'
import Guests from './guests.js'

const AuthFinder = withAuthFinder(() => hash.use('scrypt'), {
  uids: ['email'],
  passwordColumnName: 'password',
})

export default class User extends compose(BaseModel, AuthFinder) {
  @column({ isPrimary: true })
  public id!: number

  @column()
  public googleId!: string

  @column()
  public email!: string

  @column()
  public name?: string | null

  @column()
  public avatar?: string | null

  @column()
  public accessToken?: string | null

  @column()
  public refreshToken?: string | ***@***me({ autoCreate: true })
  public createdAt!: ***@***me({ autoUpdate: true })
  public updatedAt!: DateTime

  @hasMany(() => Rooms)
  public rooms!: HasMany<typeof Rooms>

  @hasMany(() => Guests)
  public guests!: HasMany<typeof Guests>

  static accessTokens = DbAccessTokensProvider.forModel(User)
}
auth :

import { defineConfig } from '@adonisjs/auth'
import { sessionGuard, sessionUserProvider } from '@adonisjs/auth/session'
import type { InferAuthEvents, Authenticators } from '@adonisjs/auth/types'

const authConfig = defineConfig({
  default: 'web',
  guards: {
    web: sessionGuard({
      useRememberMeTokens: false,
      provider: sessionUserProvider({
        model: () => import('#models/user'),
      }),
    }),
  },
})

export default authConfig

/**
 * Inferring types from the configured auth
 * guards.
 */
declare module '@adonisjs/auth/types' {
  export interface Authenticators extends InferAuthenticators<typeof authConfig> {}
}
declare module '@adonisjs/core/types' {
  interface EventsList extends InferAuthEvents<Authenticators> {}
}

session :

import env from '#start/env'
import { defineConfig, stores } from '@adonisjs/session'

const sessionConfig = defineConfig({
  enabled: true,
  cookieName: 'adonis-session',

  /**
   * When set to true, the session id cookie will be deleted
   * once the user closes the browser.
   */
  clearWithBrowser: false,

  /**
   * Define how long to keep the session data alive without
   * any activity.
   */
  age: '2h',

  /**
   * Configuration for session cookie and the
   * cookie store
   */
  cookie: {
    path: '/',
    httpOnly: true,
    secure: false,
    sameSite: false,
  },

  /**
   * The store to use. Make sure to validate the environment
   * variable in order to infer the store name without any
   * errors.
   */
  store: env.get('SESSION_DRIVER'),

  /**
   * List of configured stores. Refer documentation to see
   * list of available stores and their config.
   */
  stores: {
    cookie: stores.cookie(),
  },
})

export default sessionConfig
A voir également: