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 | 1x 2x 2x 2x 2x 2x 5x 5x 5x 1x 4x 4x 4x 4x 4x 4x 5x 5x 5x 5x 5x 5x 14x 14x | import { HttpService, Inject, Injectable } from "@nestjs/common"; import { AxiosError } from "axios"; import { THIRD_PARTY_OPTIONS_PROVIDER } from "./constants"; import { ConfigDetail, FacebookDebugTokenInfo, FacebookUserInfo, IThirdPartyAuthPluginOptions } from "./interfaces"; import path from 'path' @Injectable() export class FacebookAuthService { private endpoint: string = 'https://graph.facebook.com' private version: string = 'v16.0' private optionDetail: ConfigDetail constructor( @Inject(HttpService) private httpService: HttpService, @Inject(THIRD_PARTY_OPTIONS_PROVIDER) private options: Required<IThirdPartyAuthPluginOptions> ) { this.optionDetail = options.facebook } /** * The flow to verify a token will be: * * 1. Generate app_token using client_id, and client_secret * 2. Inspect the token below using app_token * 3. Call /me endpoint on behalf of user to get user's email * * @param token the token is retrieved from Facebook dialog in front-end */ async verify(token: string) { const appToken = await this.generateAppToken() const tokenDebugInfo = await this.inspectToken(token, appToken) if (!tokenDebugInfo.is_valid) { throw new Error('Token is invalid') } Iif (!tokenDebugInfo.scopes.includes('email')) { throw new Error('User not grant "email" permission') } const userInfo = await this.getUserInfo(token) return userInfo } private async getUserInfo(token: string): Promise<FacebookUserInfo> { const url = this.constructUrl('me') const res = await this.httpService.get<FacebookUserInfo>(url, { params: { fields: ['id', 'email', 'first_name', 'last_name'].join(), }, headers: { "Authorization": `Bearer ${token}` } }).toPromise() return res.data } private async inspectToken(token: string, appToken: string): Promise<FacebookDebugTokenInfo> { const url = this.constructUrl('debug_token', false) const res = await this.httpService.get<{data: FacebookDebugTokenInfo}>(url, { params: { input_token: token, access_token: appToken } }).toPromise() return res.data.data } private async generateAppToken(): Promise<string> { const url = this.constructUrl('oauth/access_token', false) const res = await this.httpService.get<{access_token: string}>(url, { params: { client_id: this.optionDetail.clientId, client_secret: this.optionDetail.clientSecret, grant_type: 'client_credentials' }}).toPromise() return res.data.access_token } private constructUrl(edge: string, withVersion: boolean = true) { const url = path.join(this.endpoint, withVersion ? this.version : '', edge) return url.toString() } } |