{"version":3,"sources":["../../../src/oauth2/provider/facebook.ts"],"sourcesContent":["import { invariant } from '@shware/utils';\nimport { OAuth2Error } from '../error';\nimport type { LoginOAuth2NativeParams, OAuth2Token, Provider } from '../types';\nimport { createAuthorizationUri, exchangeAuthorizationCode, verifyIdToken } from './common';\n\n/**\n * ref: https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow/\n * ref: https://developers.facebook.com/tools/explorer\n * */\nexport function createFacebookProvider(): Provider {\n  return {\n    authorizationUri: 'https://www.facebook.com/v21.0/dialog/oauth',\n    tokenUri: 'https://graph.facebook.com/v19.0/oauth/access_token',\n    userInfoUri: 'https://graph.facebook.com/me',\n    jwkSetUri: 'https://limited.facebook.com/.well-known/oauth/openid/jwks/',\n    userNameAttribute: 'id',\n    defaultScope: ['profile', 'email'],\n    createAuthorizationUri({ pkce: _, ...params }) {\n      return createAuthorizationUri({\n        ...params,\n        scope: params.scope ?? this.defaultScope,\n        authorizationUri: this.authorizationUri,\n      });\n    },\n    async exchangeAuthorizationCode({ pkce: _, ...params }) {\n      const response = await exchangeAuthorizationCode({ ...params, tokenUri: this.tokenUri });\n      if (!response.ok) {\n        const { error } = (await response.json()) as FacebookErrorResponse;\n        throw new OAuth2Error(response.status, 'invalid_request', error.message);\n      }\n      return (await response.json()) as FacebookToken;\n    },\n    async getUserInfo({ id_token, access_token }) {\n      invariant(this.jwkSetUri, 'jwkSetUri is required');\n      if (id_token) {\n        const data = await verifyIdToken<FacebookDecodedIdToken>(id_token, this.jwkSetUri);\n        return {\n          data,\n          claims: {\n            sub: data.sub,\n            name: data.name,\n            picture: data.picture,\n            email: data.email,\n            email_verified: true,\n          },\n        };\n      }\n      invariant(access_token, 'access_token is required');\n      invariant(this.userInfoUri, 'userInfoUri is required');\n\n      const url = new URL(this.userInfoUri);\n      const fields = ['id', 'name', 'email', 'picture.width(320).height(320)'];\n      url.searchParams.append('access_token', access_token);\n      url.searchParams.append('fields', fields.join(','));\n      const headers = { Accept: 'application/json' };\n      const response = await fetch(url.href, { headers });\n      if (!response.ok) {\n        throw new OAuth2Error(response.status, 'invalid_request', 'Failed to fetch user info');\n      }\n      const data = (await response.json()) as FacebookUserInfo;\n      return {\n        data,\n        claims: {\n          sub: data.id,\n          name: data.name,\n          email: data.email,\n          picture: data.picture.data.url,\n          email_verified: data.email_verified,\n        },\n      };\n    },\n    async loginOAuth2Native({ credentials }: LoginOAuth2NativeParams) {\n      if (credentials.id_token || credentials.access_token) {\n        const userInfo = await this.getUserInfo(credentials as unknown as OAuth2Token);\n        const token: OAuth2Token = {\n          token_type: 'bearer',\n          access_token: credentials.access_token ?? '',\n          id_token: credentials.id_token,\n        };\n        return { token, userInfo };\n      } else {\n        throw new OAuth2Error(400, 'invalid_request', 'id_token or access_token is required');\n      }\n    },\n  };\n}\n\nexport const facebook = createFacebookProvider();\n\nexport interface FacebookDecodedIdToken {\n  sub: string;\n  name: string;\n  email: string;\n  picture: string;\n  nonce?: string;\n}\n\nexport interface FacebookUserInfo {\n  id: string;\n  name: string;\n  email: string;\n  email_verified: boolean;\n  picture: {\n    data: {\n      url: string;\n      width: number;\n      height: number;\n      is_silhouette: boolean;\n    };\n  };\n}\n\nexport interface FacebookToken extends OAuth2Token {\n  access_token: string;\n  token_type: 'bearer';\n  expires_in: number;\n  id_token?: string;\n}\n\nexport type FacebookAppCredential =\n  | { state: string; id_token: string } // platform=ios and tracking=limited\n  | { state: string; access_token: string }; // tracking=enabled\n\ninterface FacebookErrorResponse {\n  error: {\n    message: string;\n    type: 'OAuthException';\n    code: number;\n    error_subcode: number;\n    fbtrace_id: string;\n  };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA0B;AAC1B,mBAA4B;AAE5B,oBAAiF;AAM1E,SAAS,yBAAmC;AACjD,SAAO;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,cAAc,CAAC,WAAW,OAAO;AAAA,IACjC,uBAAuB,EAAE,MAAM,GAAG,GAAG,OAAO,GAAG;AAC7C,iBAAO,sCAAuB;AAAA,QAC5B,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,KAAK;AAAA,QAC5B,kBAAkB,KAAK;AAAA,MACzB,CAAC;AAAA,IACH;AAAA,IACA,MAAM,0BAA0B,EAAE,MAAM,GAAG,GAAG,OAAO,GAAG;AACtD,YAAM,WAAW,UAAM,yCAA0B,EAAE,GAAG,QAAQ,UAAU,KAAK,SAAS,CAAC;AACvF,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,EAAE,MAAM,IAAK,MAAM,SAAS,KAAK;AACvC,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,MAAM,OAAO;AAAA,MACzE;AACA,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAAA,IACA,MAAM,YAAY,EAAE,UAAU,aAAa,GAAG;AAC5C,kCAAU,KAAK,WAAW,uBAAuB;AACjD,UAAI,UAAU;AACZ,cAAMA,QAAO,UAAM,6BAAsC,UAAU,KAAK,SAAS;AACjF,eAAO;AAAA,UACL,MAAAA;AAAA,UACA,QAAQ;AAAA,YACN,KAAKA,MAAK;AAAA,YACV,MAAMA,MAAK;AAAA,YACX,SAASA,MAAK;AAAA,YACd,OAAOA,MAAK;AAAA,YACZ,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AACA,kCAAU,cAAc,0BAA0B;AAClD,kCAAU,KAAK,aAAa,yBAAyB;AAErD,YAAM,MAAM,IAAI,IAAI,KAAK,WAAW;AACpC,YAAM,SAAS,CAAC,MAAM,QAAQ,SAAS,gCAAgC;AACvE,UAAI,aAAa,OAAO,gBAAgB,YAAY;AACpD,UAAI,aAAa,OAAO,UAAU,OAAO,KAAK,GAAG,CAAC;AAClD,YAAM,UAAU,EAAE,QAAQ,mBAAmB;AAC7C,YAAM,WAAW,MAAM,MAAM,IAAI,MAAM,EAAE,QAAQ,CAAC;AAClD,UAAI,CAAC,SAAS,IAAI;AAChB,cAAM,IAAI,yBAAY,SAAS,QAAQ,mBAAmB,2BAA2B;AAAA,MACvF;AACA,YAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,aAAO;AAAA,QACL;AAAA,QACA,QAAQ;AAAA,UACN,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK,QAAQ,KAAK;AAAA,UAC3B,gBAAgB,KAAK;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM,kBAAkB,EAAE,YAAY,GAA4B;AAChE,UAAI,YAAY,YAAY,YAAY,cAAc;AACpD,cAAM,WAAW,MAAM,KAAK,YAAY,WAAqC;AAC7E,cAAM,QAAqB;AAAA,UACzB,YAAY;AAAA,UACZ,cAAc,YAAY,gBAAgB;AAAA,UAC1C,UAAU,YAAY;AAAA,QACxB;AACA,eAAO,EAAE,OAAO,SAAS;AAAA,MAC3B,OAAO;AACL,cAAM,IAAI,yBAAY,KAAK,mBAAmB,sCAAsC;AAAA,MACtF;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,WAAW,uBAAuB;","names":["data"]}