Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | 12x 12x 12x 12x 12x 5x 1x 4x 3x 3x 2x 2x 1x 2x 2x 1x 2x 2x 1x 1x | import { Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { HttpService } from '@nestjs/axios'
import { firstValueFrom } from 'rxjs'
import { AuthProvider, AuthUser, Auth0UserProfile } from './auth-provider.interface'
@Injectable()
export class Auth0Provider implements AuthProvider {
private domain: string
private clientId: string
private clientSecret: string
constructor(
private configService: ConfigService,
private readonly httpService: HttpService,
) {
this.domain = this.configService.get<string>('AUTH0_DOMAIN') || ''
this.clientId = this.configService.get<string>('AUTH0_CLIENT_ID') || ''
this.clientSecret = this.configService.get<string>('AUTH0_CLIENT_SECRET') || ''
}
async verify(credentials: Record<string, any>): Promise<AuthUser | null> {
// Case 1: External Trusted Provider (Pre-verified by Strategy)
if (credentials.isTrusted && credentials.email) {
// Logic: You might want to check if this email exists in Auth0 or just allow it
// For now, mirroring LocalProvider: if email matches Admin or is valid User in Auth0
return {
id: credentials.sub || 'auth0_user',
email: credentials.email,
role: 'USER', // Default to USER, or map from Auth0 roles
name: credentials.name,
picture: credentials.picture,
}
}
// Case 2: Email/Password Login (Resource Owner Password Grant)
// Warning: correct configuration in Auth0 (Grant Types) is required.
if (credentials.email && credentials.password) {
try {
const { data } = await firstValueFrom(
this.httpService.post(
`https://${this.domain}/oauth/token`,
{
grant_type: 'password',
username: credentials.email,
password: credentials.password,
audience: `https://${this.domain}/api/v2/`,
client_id: this.clientId,
client_secret: this.clientSecret,
scope: 'openid profile email',
},
{
headers: { 'content-type': 'application/json' },
},
),
)
const { access_token } = data
// Optionally fetch user profile with the token
const userProfile = await this.getUserProfile(access_token)
return {
id: userProfile.sub,
email: userProfile.email,
role: 'USER', // You'd need a way to determine Admin/Staff from Auth0 metadata/roles
name: userProfile.name,
picture: userProfile.picture,
}
} catch (error) {
console.error('Auth0 Verification Failed:', error.message)
return null
}
}
return null
}
private async getUserProfile(accessToken: string): Promise<Auth0UserProfile> {
try {
const { data } = await firstValueFrom(
this.httpService.get(`https://${this.domain}/userinfo`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
}),
)
return data
} catch (_error) {
throw new Error('Failed to fetch user profile')
}
}
}
|