@magic-ext/react-native-expo-oauth 30.3.2-canary.1042.22302271458.0 → 30.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var y=Object.create;var u=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var b=Object.getPrototypeOf,O=Object.prototype.hasOwnProperty;var U=(e,r)=>{for(var n in r)u(e,n,{get:r[n],enumerable:!0})},g=(e,r,n,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of I(r))!O.call(e,i)&&i!==n&&u(e,i,{get:()=>r[i],enumerable:!(t=A(r,i))||t.enumerable});return e};var x=(e,r,n)=>(n=e!=null?y(b(e)):{},g(r||!e||!e.__esModule?u(n,"default",{value:e,enumerable:!0}):n,e)),k=e=>g(u({},"__esModule",{value:!0}),e);var D={};U(D,{OAuthErrorCode:()=>h,OAuthExtension:()=>l,OAuthPayloadMethods:()=>d,getResult:()=>f});module.exports=k(D);var R=x(require("expo-web-browser")),m=require("@magic-sdk/react-native-expo");var d=(t=>(t.Start="magic_oauth_login_with_redirect_start",t.Verify="magic_oauth_login_with_redirect_verify",t.Popup="magic_oauth_login_with_popup",t))(d||{}),h=(o=>(o.InvalidRequest="invalid_request",o.InvalidClient="invalid_client",o.InvalidScope="invalid_scope",o.InvalidGrant="invalid_grant",o.UnauthorizedClient="unauthorized_client",o.UnsupportedResponseType="unsupported_response_type",o.UnsupportedGrantType="unsupported_grant_type",o.UnsupportedTokenType="unsupported_token_type",o.AccessDenied="access_denied",o.ServerError="server_error",o.TemporarilyUnavailable="temporarily_unavailable",o))(h||{});var l=class extends m.Extension.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(r){return this.utils.createPromiEvent(async(n,t)=>{try{let i=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...r,apiKey:this.sdk.apiKey,platform:"rn"}]),c=await this.request(i),s=c,a=c;if(a.error){t(this.createError(a.error,a.error_description??"An error occurred.",{errorURI:a.error_uri,provider:a.provider}));return}if(!s?.oauthAuthoriationURI){t(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let _=new URL(s.oauthAuthoriationURI,"https://auth.magic.link/").href,p=await R.openAuthSessionAsync(_,r.redirectURI,{});if(p.type==="success"){let v=new URL(p.url).search;n(f.call(this,v.toString()))}else t(this.createError(p.type,"User has cancelled the authentication",{}))}catch(i){t(this.createError(i.message,"An error has occurred",{err:i}))}})}};function f(e){return this.utils.createPromiEvent(async(r,n)=>{let t=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:e,magicApiKey:this.sdk.apiKey,platform:"rn"}]),i=await this.request(t),c=i,s=i;s.error&&n(this.createError(s.error,s.error_description??"An error occurred.",{errorURI:s.error_uri,provider:s.provider})),r(c)})}0&&(module.exports={OAuthErrorCode,OAuthExtension,OAuthPayloadMethods,getResult});
1
+ "use strict";var x=Object.create;var p=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var P=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var E=(r,e)=>{for(var t in e)p(r,t,{get:e[t],enumerable:!0})},b=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of w(e))!D.call(r,a)&&a!==t&&p(r,a,{get:()=>e[a],enumerable:!(i=k(e,a))||i.enumerable});return r};var v=(r,e,t)=>(t=r!=null?x(P(r)):{},b(e||!r||!r.__esModule?p(t,"default",{value:r,enumerable:!0}):t,r)),T=r=>b(p({},"__esModule",{value:!0}),r);var N={};E(N,{OAuthErrorCode:()=>A,OAuthExtension:()=>R,OAuthPayloadMethods:()=>h,getResult:()=>C});module.exports=T(N);var O=v(require("expo-web-browser")),S=require("@magic-sdk/react-native-expo");var h=(i=>(i.Start="magic_oauth_login_with_redirect_start",i.Verify="magic_oauth_login_with_redirect_verify",i.Popup="magic_oauth_login_with_popup",i))(h||{}),A=(n=>(n.InvalidRequest="invalid_request",n.InvalidClient="invalid_client",n.InvalidScope="invalid_scope",n.InvalidGrant="invalid_grant",n.UnauthorizedClient="unauthorized_client",n.UnsupportedResponseType="unsupported_response_type",n.UnsupportedGrantType="unsupported_grant_type",n.UnsupportedTokenType="unsupported_token_type",n.AccessDenied="access_denied",n.ServerError="server_error",n.TemporarilyUnavailable="temporarily_unavailable",n))(A||{});var m=v(require("crypto-js")),V=typeof global<"u"&&typeof global.crypto?.getRandomValues=="function";function q(r){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";return Array.from(r).map(t=>e[t%e.length]).join("")}function I(r){if(!V)throw new Error("Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).");let e=new Uint8Array(r);return global.crypto.getRandomValues(e),q(e)}function M(r){return r.toString(m.default.enc.Base64).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function U(){let r=I(128),e=I(128),t=M(m.default.SHA256(e));return{codeVerifier:e,codeChallenge:t,cryptoChallengeState:r}}var R=class extends S.Extension.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(e){return this.utils.createPromiEvent(async(t,i)=>{try{let{codeVerifier:a,codeChallenge:c,cryptoChallengeState:l}=U(),o=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...e,apiKey:this.sdk.apiKey,platform:"rn",codeChallenge:c,cryptoChallengeState:l}]),f=await this.request(o),u=f,s=f;if(s.error){i(this.createError(s.error,s.error_description??"An error occurred.",{errorURI:s.error_uri,provider:s.provider}));return}if(!u?.oauthAuthoriationURI){i(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let n=new URL(u.oauthAuthoriationURI,"https://auth.magic.link/").href,d=await O.openAuthSessionAsync(n,e.redirectURI,{});if(d.type==="success"){let y=new URL(d.url).search,g=u.pkceMetadata?{codeVerifier:a,...u.pkceMetadata}:void 0;if(g){let _=new URLSearchParams(y).get("state");if(!_||_!==g.state){i(this.createError("STATE_MISMATCH","OAuth state parameter mismatch \u2014 request may have been tampered with",{}));return}}t(C.call(this,y.toString(),g))}else i(this.createError(d.type,"User has cancelled the authentication",{}))}catch(a){i(this.createError(a.message,"An error has occurred",{err:a}))}})}};function C(r,e){return this.utils.createPromiEvent(async(t,i)=>{let a=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:r,magicApiKey:this.sdk.apiKey,platform:"rn",...e?{clientMetadata:e}:{}}]),c=await this.request(a),l=c,o=c;o.error&&i(this.createError(o.error,o.error_description??"An error occurred.",{errorURI:o.error_uri,provider:o.provider})),t(l)})}0&&(module.exports={OAuthErrorCode,OAuthExtension,OAuthPayloadMethods,getResult});
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/index.ts", "../../src/types.ts"],
4
- "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n resolve(getResult.call(this, queryString.toString()));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n}\n"],
5
- "mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,EAAA,mBAAAC,EAAA,wBAAAC,EAAA,cAAAC,IAAA,eAAAC,EAAAN,GAAA,IAAAO,EAA4B,+BAC5BC,EAA0B,wCCCnB,IAAKC,OACVA,EAAA,MAAQ,wCACRA,EAAA,OAAS,yCACTA,EAAA,MAAQ,+BAHEA,OAAA,IAgGAC,OACVA,EAAA,eAAiB,kBACjBA,EAAA,cAAgB,iBAChBA,EAAA,aAAe,gBACfA,EAAA,aAAe,gBACfA,EAAA,mBAAqB,sBACrBA,EAAA,wBAA0B,4BAC1BA,EAAA,qBAAuB,yBACvBA,EAAA,qBAAuB,yBACvBA,EAAA,aAAe,gBACfA,EAAA,YAAc,eACdA,EAAA,uBAAyB,0BAXfA,OAAA,IDvFL,IAAMC,EAAN,cAA6B,YAAU,QAAkB,CAC9D,KAAO,QACP,OAAS,CAAC,EACV,OAAS,CACP,YAAa,GACb,0BAA2B,GAC3B,+BAAgC,GAChC,+BAAgC,UAClC,EAEO,eAAeC,EAA2C,CAC/D,OAAO,KAAK,MAAM,iBAAsC,MAAOC,EAASC,IAAW,CACjF,GAAI,CACF,IAAMC,EAAe,KAAK,MAAM,oEAAuD,CACrF,CACE,GAAGH,EACH,OAAQ,KAAK,IAAI,OACjB,SAAU,IACZ,CACF,CAAC,EAEKI,EAAS,MAAM,KAAK,QAAuDD,CAAY,EACvFE,EAAgBD,EAChBE,EAAcF,EAEpB,GAAIE,EAAY,MAAO,CACrBJ,EACE,KAAK,YAA4BI,EAAY,MAAOA,EAAY,mBAAqB,qBAAsB,CACzG,SAAUA,EAAY,UACtB,SAAUA,EAAY,QACxB,CAAC,CACH,EACA,MACF,CAEA,GAAI,CAACD,GAAe,qBAAsB,CACxCH,EAAO,KAAK,YAAoB,cAAe,oCAAqC,CAAC,CAAC,CAAC,EACvF,MACF,CAEA,IAAMK,EAAM,IAAI,IAAIF,EAAc,qBAAsB,0BAA0B,EAAE,KAC9EG,EAAM,MAAiB,uBAAqBD,EAAKP,EAAc,YAAa,CAAC,CAAC,EAEpF,GAAIQ,EAAI,OAAS,UAAW,CAC1B,IAAMC,EAAc,IAAI,IAAID,EAAI,GAAG,EAAE,OACrCP,EAAQS,EAAU,KAAK,KAAMD,EAAY,SAAS,CAAC,CAAC,CACtD,MACEP,EAAO,KAAK,YAAoBM,EAAI,KAAM,wCAAyC,CAAC,CAAC,CAAC,CAE1F,OAASG,EAAU,CACjBT,EACE,KAAK,YAAoBS,EAAI,QAAS,wBAAyB,CAC7D,IAAAA,CACF,CAAC,CACH,CACF,CACF,CAAC,CACH,CACF,EAEO,SAASD,EAAgCD,EAAqB,CACnE,OAAO,KAAK,MAAM,iBAAsC,MAAOR,EAASC,IAAW,CACjF,IAAMU,EAAsB,KAAK,MAAM,qEAAwD,CAC7F,CACE,4BAA6BH,EAC7B,YAAa,KAAK,IAAI,OACtB,SAAU,IACZ,CACF,CAAC,EAGKI,EAAgB,MAAM,KAAK,QAAkDD,CAAmB,EAChGE,EAAcD,EACdE,EAAaF,EAEfE,EAAW,OACbb,EACE,KAAK,YAA4Ba,EAAW,MAAOA,EAAW,mBAAqB,qBAAsB,CACvG,SAAUA,EAAW,UACrB,SAAUA,EAAW,QACvB,CAAC,CACH,EAGFd,EAAQa,CAAW,CACrB,CAAC,CACH",
6
- "names": ["index_exports", "__export", "OAuthErrorCode", "OAuthExtension", "OAuthPayloadMethods", "getResult", "__toCommonJS", "WebBrowser", "import_react_native_expo", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "configuration", "resolve", "reject", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
3
+ "sources": ["../../src/index.ts", "../../src/types.ts", "../../src/crypto.ts"],
4
+ "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\nimport { createCryptoChallenge } from './crypto';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { codeVerifier, codeChallenge, cryptoChallengeState } = createCryptoChallenge();\n\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n codeChallenge,\n cryptoChallengeState,\n // codeVerifier is intentionally NOT sent here \u2014 it stays in the SDK closure.\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n // Build clientMetadata from closure \u2014 codeVerifier and pkceMetadata never left this scope.\n const clientMetadata = successResult.pkceMetadata\n ? { codeVerifier, ...successResult.pkceMetadata }\n : undefined;\n\n // State verification for the new PKCE path.\n // The extension generated the state, so it verifies it here \u2014 before any RPC call \u2014 as CSRF protection.\n // In the legacy path (no clientMetadata), embedded-wallet handles state verification itself.\n if (clientMetadata) {\n const returnedState = new URLSearchParams(queryString).get('state');\n if (!returnedState || returnedState !== clientMetadata.state) {\n reject(this.createError<object>('STATE_MISMATCH', 'OAuth state parameter mismatch \u2014 request may have been tampered with', {}));\n return;\n }\n }\n\n resolve(getResult.call(this, queryString.toString(), clientMetadata));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(\n this: OAuthExtension,\n queryString: string,\n clientMetadata?: Record<string, string>,\n) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n // Forward full metadata from closure (new PKCE path).\n // When absent, embedded-wallet falls back to its stored metadata (backward compat).\n ...(clientMetadata ? { clientMetadata } : {}),\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n /** Present in the new client-PKCE path; forwarded with codeVerifier in the verify call. */\n pkceMetadata?: {\n state: string;\n redirectUri: string;\n appID: string;\n provider: string;\n };\n}\n", "import CryptoJS from 'crypto-js';\n\n// In React Native, `window` is undefined; crypto is available at `global.crypto` in Hermes (RN 0.70+).\n// We intentionally do NOT fall back to Math.random; PKCE requires crypto.getRandomValues for secure entropy.\nconst HAS_BUILT_IN_CRYPTO =\n typeof global !== 'undefined' && typeof (global as any).crypto?.getRandomValues === 'function';\n\nfunction bytesToOAuth2CompatibleString(bytes: Uint8Array): string {\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\n return Array.from(bytes)\n .map((value) => charset[value % charset.length])\n .join('');\n}\n\nfunction createRandomString(size: number): string {\n if (!HAS_BUILT_IN_CRYPTO) {\n throw new Error('Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).');\n }\n const bytes = new Uint8Array(size);\n (global as any).crypto.getRandomValues(bytes);\n return bytesToOAuth2CompatibleString(bytes);\n}\n\nfunction verifierToBase64URL(input: CryptoJS.lib.WordArray): string {\n return input.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nexport function createCryptoChallenge(): { codeVerifier: string; codeChallenge: string; cryptoChallengeState: string } {\n const cryptoChallengeState = createRandomString(128);\n const codeVerifier = createRandomString(128);\n const codeChallenge = verifierToBase64URL(CryptoJS.SHA256(codeVerifier));\n return { codeVerifier, codeChallenge, cryptoChallengeState };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "OAuthErrorCode", "OAuthExtension", "OAuthPayloadMethods", "getResult", "__toCommonJS", "WebBrowser", "import_react_native_expo", "OAuthPayloadMethods", "OAuthErrorCode", "import_crypto_js", "HAS_BUILT_IN_CRYPTO", "bytesToOAuth2CompatibleString", "bytes", "charset", "value", "createRandomString", "size", "verifierToBase64URL", "input", "CryptoJS", "createCryptoChallenge", "cryptoChallengeState", "codeVerifier", "codeChallenge", "OAuthExtension", "configuration", "resolve", "reject", "codeVerifier", "codeChallenge", "cryptoChallengeState", "createCryptoChallenge", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "clientMetadata", "returnedState", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
7
7
  }
package/dist/es/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import*as l from"expo-web-browser";import{Extension as m}from"@magic-sdk/react-native-expo";var p=(r=>(r.Start="magic_oauth_login_with_redirect_start",r.Verify="magic_oauth_login_with_redirect_verify",r.Popup="magic_oauth_login_with_popup",r))(p||{}),R=(e=>(e.InvalidRequest="invalid_request",e.InvalidClient="invalid_client",e.InvalidScope="invalid_scope",e.InvalidGrant="invalid_grant",e.UnauthorizedClient="unauthorized_client",e.UnsupportedResponseType="unsupported_response_type",e.UnsupportedGrantType="unsupported_grant_type",e.UnsupportedTokenType="unsupported_token_type",e.AccessDenied="access_denied",e.ServerError="server_error",e.TemporarilyUnavailable="temporarily_unavailable",e))(R||{});var d=class extends m.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(o){return this.utils.createPromiEvent(async(a,r)=>{try{let i=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...o,apiKey:this.sdk.apiKey,platform:"rn"}]),s=await this.request(i),t=s,n=s;if(n.error){r(this.createError(n.error,n.error_description??"An error occurred.",{errorURI:n.error_uri,provider:n.provider}));return}if(!t?.oauthAuthoriationURI){r(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let g=new URL(t.oauthAuthoriationURI,"https://auth.magic.link/").href,c=await l.openAuthSessionAsync(g,o.redirectURI,{});if(c.type==="success"){let h=new URL(c.url).search;a(f.call(this,h.toString()))}else r(this.createError(c.type,"User has cancelled the authentication",{}))}catch(i){r(this.createError(i.message,"An error has occurred",{err:i}))}})}};function f(u){return this.utils.createPromiEvent(async(o,a)=>{let r=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:u,magicApiKey:this.sdk.apiKey,platform:"rn"}]),i=await this.request(r),s=i,t=i;t.error&&a(this.createError(t.error,t.error_description??"An error occurred.",{errorURI:t.error_uri,provider:t.provider})),o(s)})}export{R as OAuthErrorCode,d as OAuthExtension,p as OAuthPayloadMethods,f as getResult};
1
+ import*as v from"expo-web-browser";import{Extension as S}from"@magic-sdk/react-native-expo";var R=(t=>(t.Start="magic_oauth_login_with_redirect_start",t.Verify="magic_oauth_login_with_redirect_verify",t.Popup="magic_oauth_login_with_popup",t))(R||{}),A=(r=>(r.InvalidRequest="invalid_request",r.InvalidClient="invalid_client",r.InvalidScope="invalid_scope",r.InvalidGrant="invalid_grant",r.UnauthorizedClient="unauthorized_client",r.UnsupportedResponseType="unsupported_response_type",r.UnsupportedGrantType="unsupported_grant_type",r.UnsupportedTokenType="unsupported_token_type",r.AccessDenied="access_denied",r.ServerError="server_error",r.TemporarilyUnavailable="temporarily_unavailable",r))(A||{});import y from"crypto-js";var I=typeof global<"u"&&typeof global.crypto?.getRandomValues=="function";function U(i){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";return Array.from(i).map(n=>e[n%e.length]).join("")}function f(i){if(!I)throw new Error("Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).");let e=new Uint8Array(i);return global.crypto.getRandomValues(e),U(e)}function O(i){return i.toString(y.enc.Base64).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function _(){let i=f(128),e=f(128),n=O(y.SHA256(e));return{codeVerifier:e,codeChallenge:n,cryptoChallengeState:i}}var b=class extends S.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(e){return this.utils.createPromiEvent(async(n,t)=>{try{let{codeVerifier:o,codeChallenge:c,cryptoChallengeState:p}=_(),a=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...e,apiKey:this.sdk.apiKey,platform:"rn",codeChallenge:c,cryptoChallengeState:p}]),g=await this.request(a),u=g,s=g;if(s.error){t(this.createError(s.error,s.error_description??"An error occurred.",{errorURI:s.error_uri,provider:s.provider}));return}if(!u?.oauthAuthoriationURI){t(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let r=new URL(u.oauthAuthoriationURI,"https://auth.magic.link/").href,l=await v.openAuthSessionAsync(r,e.redirectURI,{});if(l.type==="success"){let h=new URL(l.url).search,d=u.pkceMetadata?{codeVerifier:o,...u.pkceMetadata}:void 0;if(d){let m=new URLSearchParams(h).get("state");if(!m||m!==d.state){t(this.createError("STATE_MISMATCH","OAuth state parameter mismatch \u2014 request may have been tampered with",{}));return}}n(C.call(this,h.toString(),d))}else t(this.createError(l.type,"User has cancelled the authentication",{}))}catch(o){t(this.createError(o.message,"An error has occurred",{err:o}))}})}};function C(i,e){return this.utils.createPromiEvent(async(n,t)=>{let o=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:i,magicApiKey:this.sdk.apiKey,platform:"rn",...e?{clientMetadata:e}:{}}]),c=await this.request(o),p=c,a=c;a.error&&t(this.createError(a.error,a.error_description??"An error occurred.",{errorURI:a.error_uri,provider:a.provider})),n(p)})}export{A as OAuthErrorCode,b as OAuthExtension,R as OAuthPayloadMethods,C as getResult};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/index.ts", "../../src/types.ts"],
4
- "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n resolve(getResult.call(this, queryString.toString()));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n}\n"],
5
- "mappings": "AAAA,UAAYA,MAAgB,mBAC5B,OAAS,aAAAC,MAAiB,+BCCnB,IAAKC,OACVA,EAAA,MAAQ,wCACRA,EAAA,OAAS,yCACTA,EAAA,MAAQ,+BAHEA,OAAA,IAgGAC,OACVA,EAAA,eAAiB,kBACjBA,EAAA,cAAgB,iBAChBA,EAAA,aAAe,gBACfA,EAAA,aAAe,gBACfA,EAAA,mBAAqB,sBACrBA,EAAA,wBAA0B,4BAC1BA,EAAA,qBAAuB,yBACvBA,EAAA,qBAAuB,yBACvBA,EAAA,aAAe,gBACfA,EAAA,YAAc,eACdA,EAAA,uBAAyB,0BAXfA,OAAA,IDvFL,IAAMC,EAAN,cAA6BC,EAAU,QAAkB,CAC9D,KAAO,QACP,OAAS,CAAC,EACV,OAAS,CACP,YAAa,GACb,0BAA2B,GAC3B,+BAAgC,GAChC,+BAAgC,UAClC,EAEO,eAAeC,EAA2C,CAC/D,OAAO,KAAK,MAAM,iBAAsC,MAAOC,EAASC,IAAW,CACjF,GAAI,CACF,IAAMC,EAAe,KAAK,MAAM,oEAAuD,CACrF,CACE,GAAGH,EACH,OAAQ,KAAK,IAAI,OACjB,SAAU,IACZ,CACF,CAAC,EAEKI,EAAS,MAAM,KAAK,QAAuDD,CAAY,EACvFE,EAAgBD,EAChBE,EAAcF,EAEpB,GAAIE,EAAY,MAAO,CACrBJ,EACE,KAAK,YAA4BI,EAAY,MAAOA,EAAY,mBAAqB,qBAAsB,CACzG,SAAUA,EAAY,UACtB,SAAUA,EAAY,QACxB,CAAC,CACH,EACA,MACF,CAEA,GAAI,CAACD,GAAe,qBAAsB,CACxCH,EAAO,KAAK,YAAoB,cAAe,oCAAqC,CAAC,CAAC,CAAC,EACvF,MACF,CAEA,IAAMK,EAAM,IAAI,IAAIF,EAAc,qBAAsB,0BAA0B,EAAE,KAC9EG,EAAM,MAAiB,uBAAqBD,EAAKP,EAAc,YAAa,CAAC,CAAC,EAEpF,GAAIQ,EAAI,OAAS,UAAW,CAC1B,IAAMC,EAAc,IAAI,IAAID,EAAI,GAAG,EAAE,OACrCP,EAAQS,EAAU,KAAK,KAAMD,EAAY,SAAS,CAAC,CAAC,CACtD,MACEP,EAAO,KAAK,YAAoBM,EAAI,KAAM,wCAAyC,CAAC,CAAC,CAAC,CAE1F,OAASG,EAAU,CACjBT,EACE,KAAK,YAAoBS,EAAI,QAAS,wBAAyB,CAC7D,IAAAA,CACF,CAAC,CACH,CACF,CACF,CAAC,CACH,CACF,EAEO,SAASD,EAAgCD,EAAqB,CACnE,OAAO,KAAK,MAAM,iBAAsC,MAAOR,EAASC,IAAW,CACjF,IAAMU,EAAsB,KAAK,MAAM,qEAAwD,CAC7F,CACE,4BAA6BH,EAC7B,YAAa,KAAK,IAAI,OACtB,SAAU,IACZ,CACF,CAAC,EAGKI,EAAgB,MAAM,KAAK,QAAkDD,CAAmB,EAChGE,EAAcD,EACdE,EAAaF,EAEfE,EAAW,OACbb,EACE,KAAK,YAA4Ba,EAAW,MAAOA,EAAW,mBAAqB,qBAAsB,CACvG,SAAUA,EAAW,UACrB,SAAUA,EAAW,QACvB,CAAC,CACH,EAGFd,EAAQa,CAAW,CACrB,CAAC,CACH",
6
- "names": ["WebBrowser", "Extension", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
3
+ "sources": ["../../src/index.ts", "../../src/types.ts", "../../src/crypto.ts"],
4
+ "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\nimport { createCryptoChallenge } from './crypto';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { codeVerifier, codeChallenge, cryptoChallengeState } = createCryptoChallenge();\n\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n codeChallenge,\n cryptoChallengeState,\n // codeVerifier is intentionally NOT sent here \u2014 it stays in the SDK closure.\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n // Build clientMetadata from closure \u2014 codeVerifier and pkceMetadata never left this scope.\n const clientMetadata = successResult.pkceMetadata\n ? { codeVerifier, ...successResult.pkceMetadata }\n : undefined;\n\n // State verification for the new PKCE path.\n // The extension generated the state, so it verifies it here \u2014 before any RPC call \u2014 as CSRF protection.\n // In the legacy path (no clientMetadata), embedded-wallet handles state verification itself.\n if (clientMetadata) {\n const returnedState = new URLSearchParams(queryString).get('state');\n if (!returnedState || returnedState !== clientMetadata.state) {\n reject(this.createError<object>('STATE_MISMATCH', 'OAuth state parameter mismatch \u2014 request may have been tampered with', {}));\n return;\n }\n }\n\n resolve(getResult.call(this, queryString.toString(), clientMetadata));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(\n this: OAuthExtension,\n queryString: string,\n clientMetadata?: Record<string, string>,\n) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n // Forward full metadata from closure (new PKCE path).\n // When absent, embedded-wallet falls back to its stored metadata (backward compat).\n ...(clientMetadata ? { clientMetadata } : {}),\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n /** Present in the new client-PKCE path; forwarded with codeVerifier in the verify call. */\n pkceMetadata?: {\n state: string;\n redirectUri: string;\n appID: string;\n provider: string;\n };\n}\n", "import CryptoJS from 'crypto-js';\n\n// In React Native, `window` is undefined; crypto is available at `global.crypto` in Hermes (RN 0.70+).\n// We intentionally do NOT fall back to Math.random; PKCE requires crypto.getRandomValues for secure entropy.\nconst HAS_BUILT_IN_CRYPTO =\n typeof global !== 'undefined' && typeof (global as any).crypto?.getRandomValues === 'function';\n\nfunction bytesToOAuth2CompatibleString(bytes: Uint8Array): string {\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\n return Array.from(bytes)\n .map((value) => charset[value % charset.length])\n .join('');\n}\n\nfunction createRandomString(size: number): string {\n if (!HAS_BUILT_IN_CRYPTO) {\n throw new Error('Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).');\n }\n const bytes = new Uint8Array(size);\n (global as any).crypto.getRandomValues(bytes);\n return bytesToOAuth2CompatibleString(bytes);\n}\n\nfunction verifierToBase64URL(input: CryptoJS.lib.WordArray): string {\n return input.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nexport function createCryptoChallenge(): { codeVerifier: string; codeChallenge: string; cryptoChallengeState: string } {\n const cryptoChallengeState = createRandomString(128);\n const codeVerifier = createRandomString(128);\n const codeChallenge = verifierToBase64URL(CryptoJS.SHA256(codeVerifier));\n return { codeVerifier, codeChallenge, cryptoChallengeState };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["WebBrowser", "Extension", "OAuthPayloadMethods", "OAuthErrorCode", "CryptoJS", "HAS_BUILT_IN_CRYPTO", "bytesToOAuth2CompatibleString", "bytes", "charset", "value", "createRandomString", "size", "verifierToBase64URL", "input", "createCryptoChallenge", "cryptoChallengeState", "codeVerifier", "codeChallenge", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "codeVerifier", "codeChallenge", "cryptoChallengeState", "createCryptoChallenge", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "clientMetadata", "returnedState", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
7
7
  }
package/dist/es/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import*as l from"expo-web-browser";import{Extension as m}from"@magic-sdk/react-native-expo";var p=(r=>(r.Start="magic_oauth_login_with_redirect_start",r.Verify="magic_oauth_login_with_redirect_verify",r.Popup="magic_oauth_login_with_popup",r))(p||{}),R=(e=>(e.InvalidRequest="invalid_request",e.InvalidClient="invalid_client",e.InvalidScope="invalid_scope",e.InvalidGrant="invalid_grant",e.UnauthorizedClient="unauthorized_client",e.UnsupportedResponseType="unsupported_response_type",e.UnsupportedGrantType="unsupported_grant_type",e.UnsupportedTokenType="unsupported_token_type",e.AccessDenied="access_denied",e.ServerError="server_error",e.TemporarilyUnavailable="temporarily_unavailable",e))(R||{});var d=class extends m.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(o){return this.utils.createPromiEvent(async(a,r)=>{try{let i=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...o,apiKey:this.sdk.apiKey,platform:"rn"}]),s=await this.request(i),t=s,n=s;if(n.error){r(this.createError(n.error,n.error_description??"An error occurred.",{errorURI:n.error_uri,provider:n.provider}));return}if(!t?.oauthAuthoriationURI){r(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let g=new URL(t.oauthAuthoriationURI,"https://auth.magic.link/").href,c=await l.openAuthSessionAsync(g,o.redirectURI,{});if(c.type==="success"){let h=new URL(c.url).search;a(f.call(this,h.toString()))}else r(this.createError(c.type,"User has cancelled the authentication",{}))}catch(i){r(this.createError(i.message,"An error has occurred",{err:i}))}})}};function f(u){return this.utils.createPromiEvent(async(o,a)=>{let r=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:u,magicApiKey:this.sdk.apiKey,platform:"rn"}]),i=await this.request(r),s=i,t=i;t.error&&a(this.createError(t.error,t.error_description??"An error occurred.",{errorURI:t.error_uri,provider:t.provider})),o(s)})}export{R as OAuthErrorCode,d as OAuthExtension,p as OAuthPayloadMethods,f as getResult};
1
+ import*as v from"expo-web-browser";import{Extension as S}from"@magic-sdk/react-native-expo";var R=(t=>(t.Start="magic_oauth_login_with_redirect_start",t.Verify="magic_oauth_login_with_redirect_verify",t.Popup="magic_oauth_login_with_popup",t))(R||{}),A=(r=>(r.InvalidRequest="invalid_request",r.InvalidClient="invalid_client",r.InvalidScope="invalid_scope",r.InvalidGrant="invalid_grant",r.UnauthorizedClient="unauthorized_client",r.UnsupportedResponseType="unsupported_response_type",r.UnsupportedGrantType="unsupported_grant_type",r.UnsupportedTokenType="unsupported_token_type",r.AccessDenied="access_denied",r.ServerError="server_error",r.TemporarilyUnavailable="temporarily_unavailable",r))(A||{});import y from"crypto-js";var I=typeof global<"u"&&typeof global.crypto?.getRandomValues=="function";function U(i){let e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";return Array.from(i).map(n=>e[n%e.length]).join("")}function f(i){if(!I)throw new Error("Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).");let e=new Uint8Array(i);return global.crypto.getRandomValues(e),U(e)}function O(i){return i.toString(y.enc.Base64).replace(/=/g,"").replace(/\+/g,"-").replace(/\//g,"_")}function _(){let i=f(128),e=f(128),n=O(y.SHA256(e));return{codeVerifier:e,codeChallenge:n,cryptoChallengeState:i}}var b=class extends S.Internal{name="oauth";config={};compat={"magic-sdk":!1,"@magic-sdk/react-native":!1,"@magic-sdk/react-native-bare":!1,"@magic-sdk/react-native-expo":">=13.0.0"};loginWithPopup(e){return this.utils.createPromiEvent(async(n,t)=>{try{let{codeVerifier:o,codeChallenge:c,cryptoChallengeState:p}=_(),a=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_start",[{...e,apiKey:this.sdk.apiKey,platform:"rn",codeChallenge:c,cryptoChallengeState:p}]),g=await this.request(a),u=g,s=g;if(s.error){t(this.createError(s.error,s.error_description??"An error occurred.",{errorURI:s.error_uri,provider:s.provider}));return}if(!u?.oauthAuthoriationURI){t(this.createError("NO_AUTH_URI","No authorization URI was returned",{}));return}let r=new URL(u.oauthAuthoriationURI,"https://auth.magic.link/").href,l=await v.openAuthSessionAsync(r,e.redirectURI,{});if(l.type==="success"){let h=new URL(l.url).search,d=u.pkceMetadata?{codeVerifier:o,...u.pkceMetadata}:void 0;if(d){let m=new URLSearchParams(h).get("state");if(!m||m!==d.state){t(this.createError("STATE_MISMATCH","OAuth state parameter mismatch \u2014 request may have been tampered with",{}));return}}n(C.call(this,h.toString(),d))}else t(this.createError(l.type,"User has cancelled the authentication",{}))}catch(o){t(this.createError(o.message,"An error has occurred",{err:o}))}})}};function C(i,e){return this.utils.createPromiEvent(async(n,t)=>{let o=this.utils.createJsonRpcRequestPayload("magic_oauth_login_with_redirect_verify",[{authorizationResponseParams:i,magicApiKey:this.sdk.apiKey,platform:"rn",...e?{clientMetadata:e}:{}}]),c=await this.request(o),p=c,a=c;a.error&&t(this.createError(a.error,a.error_description??"An error occurred.",{errorURI:a.error_uri,provider:a.provider})),n(p)})}export{A as OAuthErrorCode,b as OAuthExtension,R as OAuthPayloadMethods,C as getResult};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/index.ts", "../../src/types.ts"],
4
- "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n resolve(getResult.call(this, queryString.toString()));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n}\n"],
5
- "mappings": "AAAA,UAAYA,MAAgB,mBAC5B,OAAS,aAAAC,MAAiB,+BCCnB,IAAKC,OACVA,EAAA,MAAQ,wCACRA,EAAA,OAAS,yCACTA,EAAA,MAAQ,+BAHEA,OAAA,IAgGAC,OACVA,EAAA,eAAiB,kBACjBA,EAAA,cAAgB,iBAChBA,EAAA,aAAe,gBACfA,EAAA,aAAe,gBACfA,EAAA,mBAAqB,sBACrBA,EAAA,wBAA0B,4BAC1BA,EAAA,qBAAuB,yBACvBA,EAAA,qBAAuB,yBACvBA,EAAA,aAAe,gBACfA,EAAA,YAAc,eACdA,EAAA,uBAAyB,0BAXfA,OAAA,IDvFL,IAAMC,EAAN,cAA6BC,EAAU,QAAkB,CAC9D,KAAO,QACP,OAAS,CAAC,EACV,OAAS,CACP,YAAa,GACb,0BAA2B,GAC3B,+BAAgC,GAChC,+BAAgC,UAClC,EAEO,eAAeC,EAA2C,CAC/D,OAAO,KAAK,MAAM,iBAAsC,MAAOC,EAASC,IAAW,CACjF,GAAI,CACF,IAAMC,EAAe,KAAK,MAAM,oEAAuD,CACrF,CACE,GAAGH,EACH,OAAQ,KAAK,IAAI,OACjB,SAAU,IACZ,CACF,CAAC,EAEKI,EAAS,MAAM,KAAK,QAAuDD,CAAY,EACvFE,EAAgBD,EAChBE,EAAcF,EAEpB,GAAIE,EAAY,MAAO,CACrBJ,EACE,KAAK,YAA4BI,EAAY,MAAOA,EAAY,mBAAqB,qBAAsB,CACzG,SAAUA,EAAY,UACtB,SAAUA,EAAY,QACxB,CAAC,CACH,EACA,MACF,CAEA,GAAI,CAACD,GAAe,qBAAsB,CACxCH,EAAO,KAAK,YAAoB,cAAe,oCAAqC,CAAC,CAAC,CAAC,EACvF,MACF,CAEA,IAAMK,EAAM,IAAI,IAAIF,EAAc,qBAAsB,0BAA0B,EAAE,KAC9EG,EAAM,MAAiB,uBAAqBD,EAAKP,EAAc,YAAa,CAAC,CAAC,EAEpF,GAAIQ,EAAI,OAAS,UAAW,CAC1B,IAAMC,EAAc,IAAI,IAAID,EAAI,GAAG,EAAE,OACrCP,EAAQS,EAAU,KAAK,KAAMD,EAAY,SAAS,CAAC,CAAC,CACtD,MACEP,EAAO,KAAK,YAAoBM,EAAI,KAAM,wCAAyC,CAAC,CAAC,CAAC,CAE1F,OAASG,EAAU,CACjBT,EACE,KAAK,YAAoBS,EAAI,QAAS,wBAAyB,CAC7D,IAAAA,CACF,CAAC,CACH,CACF,CACF,CAAC,CACH,CACF,EAEO,SAASD,EAAgCD,EAAqB,CACnE,OAAO,KAAK,MAAM,iBAAsC,MAAOR,EAASC,IAAW,CACjF,IAAMU,EAAsB,KAAK,MAAM,qEAAwD,CAC7F,CACE,4BAA6BH,EAC7B,YAAa,KAAK,IAAI,OACtB,SAAU,IACZ,CACF,CAAC,EAGKI,EAAgB,MAAM,KAAK,QAAkDD,CAAmB,EAChGE,EAAcD,EACdE,EAAaF,EAEfE,EAAW,OACbb,EACE,KAAK,YAA4Ba,EAAW,MAAOA,EAAW,mBAAqB,qBAAsB,CACvG,SAAUA,EAAW,UACrB,SAAUA,EAAW,QACvB,CAAC,CACH,EAGFd,EAAQa,CAAW,CACrB,CAAC,CACH",
6
- "names": ["WebBrowser", "Extension", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
3
+ "sources": ["../../src/index.ts", "../../src/types.ts", "../../src/crypto.ts"],
4
+ "sourcesContent": ["import * as WebBrowser from 'expo-web-browser';\nimport { Extension } from '@magic-sdk/react-native-expo';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\n OAuthRedirectStartResult,\n} from './types';\nimport { createCryptoChallenge } from './crypto';\n\nexport class OAuthExtension extends Extension.Internal<'oauth'> {\n name = 'oauth' as const;\n config = {};\n compat = {\n 'magic-sdk': false,\n '@magic-sdk/react-native': false,\n '@magic-sdk/react-native-bare': false,\n '@magic-sdk/react-native-expo': '>=13.0.0',\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { codeVerifier, codeChallenge, cryptoChallengeState } = createCryptoChallenge();\n\n const startPayload = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Start, [\n {\n ...configuration,\n apiKey: this.sdk.apiKey,\n platform: 'rn',\n codeChallenge,\n cryptoChallengeState,\n // codeVerifier is intentionally NOT sent here \u2014 it stays in the SDK closure.\n },\n ]);\n\n const result = await this.request<OAuthRedirectStartResult | OAuthRedirectError>(startPayload);\n const successResult = result as OAuthRedirectStartResult;\n const errorResult = result as OAuthRedirectError;\n\n if (errorResult.error) {\n reject(\n this.createError<OAuthErrorData>(errorResult.error, errorResult.error_description ?? 'An error occurred.', {\n errorURI: errorResult.error_uri,\n provider: errorResult.provider,\n }),\n );\n return;\n }\n\n if (!successResult?.oauthAuthoriationURI) {\n reject(this.createError<object>('NO_AUTH_URI', 'No authorization URI was returned', {}));\n return;\n }\n\n const url = new URL(successResult.oauthAuthoriationURI, 'https://auth.magic.link/').href;\n const res = await WebBrowser.openAuthSessionAsync(url, configuration.redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n // Build clientMetadata from closure \u2014 codeVerifier and pkceMetadata never left this scope.\n const clientMetadata = successResult.pkceMetadata\n ? { codeVerifier, ...successResult.pkceMetadata }\n : undefined;\n\n // State verification for the new PKCE path.\n // The extension generated the state, so it verifies it here \u2014 before any RPC call \u2014 as CSRF protection.\n // In the legacy path (no clientMetadata), embedded-wallet handles state verification itself.\n if (clientMetadata) {\n const returnedState = new URLSearchParams(queryString).get('state');\n if (!returnedState || returnedState !== clientMetadata.state) {\n reject(this.createError<object>('STATE_MISMATCH', 'OAuth state parameter mismatch \u2014 request may have been tampered with', {}));\n return;\n }\n }\n\n resolve(getResult.call(this, queryString.toString(), clientMetadata));\n } else {\n reject(this.createError<object>(res.type, 'User has cancelled the authentication', {}));\n }\n } catch (err: any) {\n reject(\n this.createError<object>(err.message, 'An error has occurred', {\n err,\n }),\n );\n }\n });\n }\n}\n\nexport function getResult(\n this: OAuthExtension,\n queryString: string,\n clientMetadata?: Record<string, string>,\n) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.Verify, [\n {\n authorizationResponseParams: queryString,\n magicApiKey: this.sdk.apiKey,\n platform: 'rn',\n // Forward full metadata from closure (new PKCE path).\n // When absent, embedded-wallet falls back to its stored metadata (backward compat).\n ...(clientMetadata ? { clientMetadata } : {}),\n },\n ]);\n\n // Parse the result, which may contain an OAuth-formatted error.\n const resultOrError = await this.request<OAuthRedirectResult | OAuthRedirectError>(parseRedirectResult);\n const maybeResult = resultOrError as OAuthRedirectResult;\n const maybeError = resultOrError as OAuthRedirectError;\n\n if (maybeError.error) {\n reject(\n this.createError<OAuthErrorData>(maybeError.error, maybeError.error_description ?? 'An error occurred.', {\n errorURI: maybeError.error_uri,\n provider: maybeError.provider,\n }),\n );\n }\n\n resolve(maybeResult);\n });\n}\n\nexport * from './types';\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n Start = 'magic_oauth_login_with_redirect_start',\n Verify = 'magic_oauth_login_with_redirect_verify',\n Popup = 'magic_oauth_login_with_popup',\n}\n\nexport type OAuthProvider =\n | 'google'\n | 'facebook'\n | 'apple'\n | 'github'\n | 'bitbucket'\n | 'gitlab'\n | 'linkedin'\n | 'twitter'\n | 'discord'\n | 'twitch'\n | 'microsoft';\n\nexport interface OAuthErrorData {\n provider: OAuthProvider;\n errorURI?: string;\n}\n\nexport interface OpenIDConnectProfile {\n name?: string;\n familyName?: string;\n givenName?: string;\n middleName?: string;\n nickname?: string;\n preferredUsername?: string;\n profile?: string;\n picture?: string;\n website?: string;\n gender?: string;\n birthdate?: string;\n zoneinfo?: string;\n locale?: string;\n updatedAt?: number;\n}\n\nexport interface OpenIDConnectEmail {\n email?: string;\n emailVerified?: boolean;\n}\n\nexport interface OpenIDConnectPhone {\n phoneNumber?: string;\n phoneNumberVerified?: boolean;\n}\n\nexport interface OpenIDConnectAddress {\n address?: {\n formatted?: string;\n streetAddress?: string;\n locality?: string;\n region?: string;\n postalCode?: string;\n country?: string;\n };\n}\n\nexport type OpenIDConnectUserInfo = OpenIDConnectProfile &\n OpenIDConnectEmail &\n OpenIDConnectPhone &\n OpenIDConnectAddress & { sub?: string; sources?: Record<string, any> } & Record<string, any>;\n\nexport interface OAuthRedirectResult {\n oauth: {\n provider: OAuthProvider;\n scope: string[];\n accessToken: string;\n userHandle: string;\n userInfo: OpenIDConnectUserInfo;\n };\n\n magic: {\n idToken: string;\n userMetadata: MagicUserMetadata;\n };\n}\n\nexport interface OAuthRedirectError {\n provider: OAuthProvider;\n error: string;\n error_description?: string;\n error_uri?: string;\n}\n\nexport interface OAuthRedirectConfiguration {\n provider: OAuthProvider;\n redirectURI: string;\n scope?: string[];\n loginHint?: string;\n}\n\nexport enum OAuthErrorCode {\n InvalidRequest = 'invalid_request',\n InvalidClient = 'invalid_client',\n InvalidScope = 'invalid_scope',\n InvalidGrant = 'invalid_grant',\n UnauthorizedClient = 'unauthorized_client',\n UnsupportedResponseType = 'unsupported_response_type',\n UnsupportedGrantType = 'unsupported_grant_type',\n UnsupportedTokenType = 'unsupported_token_type',\n AccessDenied = 'access_denied',\n ServerError = 'server_error',\n TemporarilyUnavailable = 'temporarily_unavailable',\n}\n\nexport interface OAuthRedirectStartResult {\n oauthAuthoriationURI?: string;\n useMagicServerCallback?: boolean;\n shouldReturnURI?: boolean;\n /** Present in the new client-PKCE path; forwarded with codeVerifier in the verify call. */\n pkceMetadata?: {\n state: string;\n redirectUri: string;\n appID: string;\n provider: string;\n };\n}\n", "import CryptoJS from 'crypto-js';\n\n// In React Native, `window` is undefined; crypto is available at `global.crypto` in Hermes (RN 0.70+).\n// We intentionally do NOT fall back to Math.random; PKCE requires crypto.getRandomValues for secure entropy.\nconst HAS_BUILT_IN_CRYPTO =\n typeof global !== 'undefined' && typeof (global as any).crypto?.getRandomValues === 'function';\n\nfunction bytesToOAuth2CompatibleString(bytes: Uint8Array): string {\n const charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\n return Array.from(bytes)\n .map((value) => charset[value % charset.length])\n .join('');\n}\n\nfunction createRandomString(size: number): string {\n if (!HAS_BUILT_IN_CRYPTO) {\n throw new Error('Secure random number generation is not available in this environment. PKCE requires crypto.getRandomValues (available in Hermes / React Native 0.70+).');\n }\n const bytes = new Uint8Array(size);\n (global as any).crypto.getRandomValues(bytes);\n return bytesToOAuth2CompatibleString(bytes);\n}\n\nfunction verifierToBase64URL(input: CryptoJS.lib.WordArray): string {\n return input.toString(CryptoJS.enc.Base64).replace(/=/g, '').replace(/\\+/g, '-').replace(/\\//g, '_');\n}\n\nexport function createCryptoChallenge(): { codeVerifier: string; codeChallenge: string; cryptoChallengeState: string } {\n const cryptoChallengeState = createRandomString(128);\n const codeVerifier = createRandomString(128);\n const codeChallenge = verifierToBase64URL(CryptoJS.SHA256(codeVerifier));\n return { codeVerifier, codeChallenge, cryptoChallengeState };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["WebBrowser", "Extension", "OAuthPayloadMethods", "OAuthErrorCode", "CryptoJS", "HAS_BUILT_IN_CRYPTO", "bytesToOAuth2CompatibleString", "bytes", "charset", "value", "createRandomString", "size", "verifierToBase64URL", "input", "createCryptoChallenge", "cryptoChallengeState", "codeVerifier", "codeChallenge", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "codeVerifier", "codeChallenge", "cryptoChallengeState", "createCryptoChallenge", "startPayload", "result", "successResult", "errorResult", "url", "res", "queryString", "clientMetadata", "returnedState", "getResult", "err", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
7
7
  }
@@ -0,0 +1,5 @@
1
+ export declare function createCryptoChallenge(): {
2
+ codeVerifier: string;
3
+ codeChallenge: string;
4
+ cryptoChallengeState: string;
5
+ };
@@ -16,7 +16,7 @@ export declare class OAuthExtension extends Extension.Internal<'oauth'> {
16
16
  "closed-by-user": () => void;
17
17
  }>;
18
18
  }
19
- export declare function getResult(this: OAuthExtension, queryString: string): import("@magic-sdk/react-native-expo").PromiEvent<OAuthRedirectResult, {
19
+ export declare function getResult(this: OAuthExtension, queryString: string, clientMetadata?: Record<string, string>): import("@magic-sdk/react-native-expo").PromiEvent<OAuthRedirectResult, {
20
20
  done: (result: OAuthRedirectResult) => void;
21
21
  error: (reason: any) => void;
22
22
  settled: () => void;
@@ -89,4 +89,11 @@ export interface OAuthRedirectStartResult {
89
89
  oauthAuthoriationURI?: string;
90
90
  useMagicServerCallback?: boolean;
91
91
  shouldReturnURI?: boolean;
92
+ /** Present in the new client-PKCE path; forwarded with codeVerifier in the verify call. */
93
+ pkceMetadata?: {
94
+ state: string;
95
+ redirectUri: string;
96
+ appID: string;
97
+ provider: string;
98
+ };
92
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magic-ext/react-native-expo-oauth",
3
- "version": "30.3.2-canary.1042.22302271458.0",
3
+ "version": "30.3.2",
4
4
  "description": "Magic SDK OAuth Extension for Expo React Native environments.",
5
5
  "author": "Magic <team@magic.link> (https://magic.link/)",
6
6
  "license": "MIT",
@@ -26,11 +26,12 @@
26
26
  ]
27
27
  },
28
28
  "dependencies": {
29
+ "crypto-js": "^4.2.0",
29
30
  "expo-web-browser": "14.0.2"
30
31
  },
31
32
  "devDependencies": {
32
- "@magic-sdk/react-native-expo": "34.2.2-canary.1042.22302271458.0",
33
- "@magic-sdk/types": "27.4.1-canary.1042.22302271458.0",
33
+ "@magic-sdk/react-native-expo": "^34.2.1",
34
+ "@magic-sdk/types": "^27.4.0",
34
35
  "@react-native-async-storage/async-storage": "^2.1.2",
35
36
  "@types/crypto-js": "~4.2.0"
36
37
  },
@@ -39,5 +40,5 @@
39
40
  "@magic-sdk/types": "^27.1.0",
40
41
  "@react-native-async-storage/async-storage": "^2.1.2"
41
42
  },
42
- "gitHead": "3c70113cfbd634eb64e1f0b82e676398912ce1a1"
43
+ "gitHead": "6ca6be5ae900f6c567a2d731f2a0701dd1f9c7dc"
43
44
  }