@magic-ext/react-native-bare-oauth 7.0.0
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/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/es/index.js +2 -0
- package/dist/es/index.js.map +7 -0
- package/dist/es/index.mjs +2 -0
- package/dist/es/index.mjs.map +7 -0
- package/dist/types/crypto.d.ts +9 -0
- package/dist/types/index.d.ts +28 -0
- package/dist/types/types.d.ts +85 -0
- package/package.json +40 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018-present Magic Labs, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var T=Object.create;var g=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var $=Object.getPrototypeOf,M=Object.prototype.hasOwnProperty;var q=(e,r)=>{for(var t in r)g(e,t,{get:r[t],enumerable:!0})},R=(e,r,t,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of B(r))!M.call(e,n)&&n!==t&&g(e,n,{get:()=>r[n],enumerable:!(s=S(r,n))||s.enumerable});return e};var A=(e,r,t)=>(t=e!=null?T($(e)):{},R(r||!e||!e.__esModule?g(t,"default",{value:e,enumerable:!0}):t,e)),H=e=>R(g({},"__esModule",{value:!0}),e);var p=(e,r,t)=>new Promise((s,n)=>{var c=o=>{try{u(t.next(o))}catch(i){n(i)}},d=o=>{try{u(t.throw(o))}catch(i){n(i)}},u=o=>o.done?s(o.value):Promise.resolve(o.value).then(c,d);u((t=t.apply(e,r)).next())});var F={};q(F,{OAuthErrorCode:()=>C,OAuthExtension:()=>y,OAuthPayloadMethods:()=>f,createURI:()=>D,getResult:()=>P});module.exports=H(F);var x=require("react-native-inappbrowser-reborn"),E=require("@magic-sdk/react-native-bare"),k=require("react-native-device-info");var _=A(require("crypto-js/sha256")),U=A(require("crypto-js/enc-base64"));var I="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",O=typeof window!="undefined"&&!!window.crypto,N=O&&!!window.crypto.subtle;function L(e){return Array.from(e).map(r=>I[r%I.length]).join("")}function b(e){let r=t=>t.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");if(e instanceof ArrayBuffer){let t=new Uint8Array(e),s=Array.from(t).map(c=>String.fromCharCode(c)).join(""),n=btoa(s);return r(n)}return r(U.default.stringify(e))}function j(e){return p(this,null,function*(){if(N){let r=new TextEncoder().encode(e);return crypto.subtle.digest("SHA-256",r).then(b)}return b((0,_.default)(e))})}function v(e){let r=new Uint8Array(e);if(O)window.crypto.getRandomValues(r);else for(let t=0;t<e;t+=1)r[t]=Math.floor(Math.random()*Math.floor(255));return L(r)}function w(){return p(this,null,function*(){let e=v(128),r=v(128),t=yield j(r);return{verifier:r,challenge:t,state:e}})}var f=(r=>(r.ParseRedirectResult="magic_oauth_parse_redirect_result",r))(f||{}),C=(a=>(a.InvalidRequest="invalid_request",a.InvalidClient="invalid_client",a.InvalidScope="invalid_scope",a.InvalidGrant="invalid_grant",a.UnauthorizedClient="unauthorized_client",a.UnsupportedResponseType="unsupported_response_type",a.UnsupportedGrantType="unsupported_grant_type",a.UnsupportedTokenType="unsupported_token_type",a.AccessDenied="access_denied",a.ServerError="server_error",a.TemporarilyUnavailable="temporarily_unavailable",a))(C||{});var y=class extends E.Extension.Internal{constructor(){super(...arguments);this.name="oauth";this.config={};this.compat={"magic-sdk":!1,"@magic-sdk/react-native-bare":">=13.0.0","@magic-sdk/react-native-expo":!1,"@magic-sdk/react-native":!1}}loginWithPopup(t){return this.utils.createPromiEvent((s,n)=>p(this,null,function*(){try{let{provider:c,query:d,redirectURI:u}=yield D.call(this,t),o=`https://auth.magic.link/v1/oauth2/${c}/start?${d}`,i=yield x.InAppBrowser.openAuth(o,u,{});if(i.type==="success"){let l=new URL(i.url).search;s(P.call(this,l.toString()))}else n(this.createError(i.type,"User has cancelled the authentication",{}))}catch(c){n(this.createError(c.message,"An error has occurred",{err:c}))}}))}},m="oauth_redirect_metadata";function D(e){return p(this,null,function*(){yield this.utils.storage.removeItem(m);let{provider:r,redirectURI:t,scope:s,loginHint:n}=e,{verifier:c,challenge:d,state:u}=yield w(),o=(0,k.getBundleId)(),i=JSON.stringify({verifier:c,state:u});return yield this.utils.storage.setItem(m,i),{query:[`magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,`magic_challenge=${encodeURIComponent(d)}`,`state=${encodeURIComponent(u)}`,`platform=${encodeURIComponent("rn")}`,s&&`scope=${encodeURIComponent(s.join(" "))}`,t&&`redirect_uri=${encodeURIComponent(t)}`,n&&`login_hint=${encodeURIComponent(n)}`,o&&`bundleId=${encodeURIComponent(o)}`].reduce((a,h)=>h?`${a}&${h}`:a),provider:r,redirectURI:t}})}function P(e){return this.utils.createPromiEvent((r,t)=>p(this,null,function*(){var l;let s=yield this.utils.storage.getItem(m),{verifier:n,state:c}=JSON.parse(s);this.utils.storage.removeItem(m);let d=this.utils.createJsonRpcRequestPayload("magic_oauth_parse_redirect_result",[e,n,c]),u=yield this.request(d),o=u,i=u;i.error&&t(this.createError(i.error,(l=i.error_description)!=null?l:"An error occurred.",{errorURI:i.error_uri,provider:i.provider})),r(o)}))}0&&(module.exports={OAuthErrorCode,OAuthExtension,OAuthPayloadMethods,createURI,getResult});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts", "../../src/crypto.ts", "../../src/types.ts"],
|
|
4
|
+
"sourcesContent": ["import { InAppBrowser } from 'react-native-inappbrowser-reborn';\nimport { Extension } from '@magic-sdk/react-native-bare';\nimport { getBundleId } from 'react-native-device-info';\nimport { createCryptoChallenge } from './crypto';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\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-bare': '>=13.0.0',\n '@magic-sdk/react-native-expo': false,\n '@magic-sdk/react-native': false,\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { provider, query, redirectURI } = await createURI.call(this, configuration);\n const url = `https://auth.magic.link/v1/oauth2/${provider}/start?${query}`;\n\n /**\n * Response Type Inspired by:\n * https://docs.expo.io/versions/latest/sdk/webbrowser/#returns\n */\n const res = await InAppBrowser.openAuth(url, redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n\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\nconst OAUTH_REDIRECT_METADATA_KEY = 'oauth_redirect_metadata';\n\nexport async function createURI(this: OAuthExtension, configuration: OAuthRedirectConfiguration) {\n // Bust any old, in-progress OAuth flows.\n await this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n // Unpack configuration, generate crypto values, and persist to storage.\n const { provider, redirectURI, scope, loginHint } = configuration;\n const { verifier, challenge, state } = await createCryptoChallenge();\n const bundleId = getBundleId();\n\n /* Stringify for RN Async storage */\n const storedData = JSON.stringify({\n verifier,\n state,\n });\n\n await this.utils.storage.setItem(OAUTH_REDIRECT_METADATA_KEY, storedData);\n\n // Formulate the initial redirect query to Magic's OAuth hub.\n // Required fields:\n // - `magic_api_key`\n // - `magic_challenge`\n // - `state`\n // - `redirect_uri`\n // - `platform`\n // Optional fields:\n // - `bundleId`\n\n const query = [\n `magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,\n `magic_challenge=${encodeURIComponent(challenge)}`,\n `state=${encodeURIComponent(state)}`,\n `platform=${encodeURIComponent('rn')}`,\n scope && `scope=${encodeURIComponent(scope.join(' '))}`,\n redirectURI && `redirect_uri=${encodeURIComponent(redirectURI)}`,\n loginHint && `login_hint=${encodeURIComponent(loginHint)}`,\n bundleId && `bundleId=${encodeURIComponent(bundleId)}`,\n ].reduce((prev, next) => (next ? `${prev}&${next}` : prev));\n\n return {\n query,\n provider,\n redirectURI,\n };\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const json: string = (await this.utils.storage.getItem(OAUTH_REDIRECT_METADATA_KEY)) as string;\n\n const { verifier, state } = JSON.parse(json);\n\n // Remove the save OAuth state from storage, it stays in memory now...\n this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.ParseRedirectResult, [\n queryString,\n verifier,\n state,\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 { WordArray } from 'crypto-js';\nimport sha256Fallback from 'crypto-js/sha256';\nimport Base64 from 'crypto-js/enc-base64';\n\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\nconst HAS_CRYPTO = typeof window !== 'undefined' && !!(window.crypto as any);\nconst HAS_SUBTLE_CRYPTO = HAS_CRYPTO && !!(window.crypto.subtle as any);\n\n/**\n * Stringifies `bytes` using the OAuth 2.0 `code_verifier` character set.\n */\nfunction bytesToVerifierString(bytes: Uint8Array) {\n return Array.from(bytes)\n .map((value: number) => CHARSET[value % CHARSET.length])\n .join('');\n}\n\n/**\n * Stringifies argument (as CryptoJS `WordArray` or EcmaScript `ArrayBuffer`)\n * and encodes to URL-safe Base64.\n */\nfunction base64URLEncodeFromByteArray(wordArray: WordArray): string;\nfunction base64URLEncodeFromByteArray(arrayBuffer: ArrayBuffer): string;\nfunction base64URLEncodeFromByteArray(arg: WordArray | ArrayBuffer): string {\n const makeURLSafe = (base64: string) => {\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n };\n\n if (arg instanceof ArrayBuffer) {\n const bytes = new Uint8Array(arg);\n const utf8Binary = Array.from(bytes)\n .map((value) => String.fromCharCode(value))\n .join('');\n\n const base64 = btoa(utf8Binary);\n return makeURLSafe(base64);\n }\n\n return makeURLSafe(Base64.stringify(arg));\n}\n\n/**\n * Produces a SHA-256 hash of the given `message`. This function first attempts\n * to use the browser's built-in `SubtleCrypto` API, falling back to\n * CryptoJS if required.\n */\nasync function sha256(message: string) {\n if (HAS_SUBTLE_CRYPTO) {\n const bytes = new TextEncoder().encode(message);\n return crypto.subtle.digest('SHA-256', bytes).then(base64URLEncodeFromByteArray);\n }\n\n return base64URLEncodeFromByteArray(sha256Fallback(message));\n}\n\n/**\n * Creates a cryptographically random string using the browser's built-in\n * `Crypto` API, falling back to `Math.random` if required.\n */\nfunction createRandomString(size: number) {\n const bytes = new Uint8Array(size);\n\n if (HAS_CRYPTO) {\n window.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < size; i += 1) bytes[i] = Math.floor(Math.random() * Math.floor(255));\n }\n\n return bytesToVerifierString(bytes);\n}\n\n/**\n * Creates OAuth 2.0-compatible `code_verifier`, `code_challenge`, and `state`\n * parameters.\n */\nexport async function createCryptoChallenge() {\n const state = createRandomString(128);\n const verifier = createRandomString(128);\n const challenge = await sha256(verifier);\n return { verifier, challenge, state };\n}\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n ParseRedirectResult = 'magic_oauth_parse_redirect_result',\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["src_exports", "__export", "OAuthErrorCode", "OAuthExtension", "OAuthPayloadMethods", "createURI", "getResult", "__toCommonJS", "import_react_native_inappbrowser_reborn", "import_react_native_bare", "import_react_native_device_info", "import_sha256", "import_enc_base64", "CHARSET", "HAS_CRYPTO", "HAS_SUBTLE_CRYPTO", "bytesToVerifierString", "bytes", "value", "base64URLEncodeFromByteArray", "arg", "makeURLSafe", "base64", "utf8Binary", "Base64", "sha256", "message", "__async", "sha256Fallback", "createRandomString", "size", "i", "createCryptoChallenge", "state", "verifier", "challenge", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "configuration", "resolve", "reject", "__async", "provider", "query", "redirectURI", "createURI", "url", "res", "queryString", "getResult", "err", "OAUTH_REDIRECT_METADATA_KEY", "scope", "loginHint", "verifier", "challenge", "state", "createCryptoChallenge", "bundleId", "storedData", "prev", "next", "_a", "json", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
|
|
7
|
+
}
|
package/dist/es/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var p=(t,e,r)=>new Promise((u,a)=>{var s=i=>{try{c(r.next(i))}catch(n){a(n)}},d=i=>{try{c(r.throw(i))}catch(n){a(n)}},c=i=>i.done?u(i.value):Promise.resolve(i.value).then(s,d);c((r=r.apply(t,e)).next())});import{InAppBrowser as x}from"react-native-inappbrowser-reborn";import{Extension as E}from"@magic-sdk/react-native-bare";import{getBundleId as k}from"react-native-device-info";import v from"crypto-js/sha256";import _ from"crypto-js/enc-base64";var f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",R=typeof window!="undefined"&&!!window.crypto,U=R&&!!window.crypto.subtle;function O(t){return Array.from(t).map(e=>f[e%f.length]).join("")}function y(t){let e=r=>r.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");if(t instanceof ArrayBuffer){let r=new Uint8Array(t),u=Array.from(r).map(s=>String.fromCharCode(s)).join(""),a=btoa(u);return e(a)}return e(_.stringify(t))}function w(t){return p(this,null,function*(){if(U){let e=new TextEncoder().encode(t);return crypto.subtle.digest("SHA-256",e).then(y)}return y(v(t))})}function h(t){let e=new Uint8Array(t);if(R)window.crypto.getRandomValues(e);else for(let r=0;r<t;r+=1)e[r]=Math.floor(Math.random()*Math.floor(255));return O(e)}function A(){return p(this,null,function*(){let t=h(128),e=h(128),r=yield w(e);return{verifier:e,challenge:r,state:t}})}var I=(e=>(e.ParseRedirectResult="magic_oauth_parse_redirect_result",e))(I||{}),C=(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))(C||{});var b=class extends E.Internal{constructor(){super(...arguments);this.name="oauth";this.config={};this.compat={"magic-sdk":!1,"@magic-sdk/react-native-bare":">=13.0.0","@magic-sdk/react-native-expo":!1,"@magic-sdk/react-native":!1}}loginWithPopup(r){return this.utils.createPromiEvent((u,a)=>p(this,null,function*(){try{let{provider:s,query:d,redirectURI:c}=yield D.call(this,r),i=`https://auth.magic.link/v1/oauth2/${s}/start?${d}`,n=yield x.openAuth(i,c,{});if(n.type==="success"){let l=new URL(n.url).search;u(P.call(this,l.toString()))}else a(this.createError(n.type,"User has cancelled the authentication",{}))}catch(s){a(this.createError(s.message,"An error has occurred",{err:s}))}}))}},g="oauth_redirect_metadata";function D(t){return p(this,null,function*(){yield this.utils.storage.removeItem(g);let{provider:e,redirectURI:r,scope:u,loginHint:a}=t,{verifier:s,challenge:d,state:c}=yield A(),i=k(),n=JSON.stringify({verifier:s,state:c});return yield this.utils.storage.setItem(g,n),{query:[`magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,`magic_challenge=${encodeURIComponent(d)}`,`state=${encodeURIComponent(c)}`,`platform=${encodeURIComponent("rn")}`,u&&`scope=${encodeURIComponent(u.join(" "))}`,r&&`redirect_uri=${encodeURIComponent(r)}`,a&&`login_hint=${encodeURIComponent(a)}`,i&&`bundleId=${encodeURIComponent(i)}`].reduce((o,m)=>m?`${o}&${m}`:o),provider:e,redirectURI:r}})}function P(t){return this.utils.createPromiEvent((e,r)=>p(this,null,function*(){var l;let u=yield this.utils.storage.getItem(g),{verifier:a,state:s}=JSON.parse(u);this.utils.storage.removeItem(g);let d=this.utils.createJsonRpcRequestPayload("magic_oauth_parse_redirect_result",[t,a,s]),c=yield this.request(d),i=c,n=c;n.error&&r(this.createError(n.error,(l=n.error_description)!=null?l:"An error occurred.",{errorURI:n.error_uri,provider:n.provider})),e(i)}))}export{C as OAuthErrorCode,b as OAuthExtension,I as OAuthPayloadMethods,D as createURI,P as getResult};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts", "../../src/crypto.ts", "../../src/types.ts"],
|
|
4
|
+
"sourcesContent": ["import { InAppBrowser } from 'react-native-inappbrowser-reborn';\nimport { Extension } from '@magic-sdk/react-native-bare';\nimport { getBundleId } from 'react-native-device-info';\nimport { createCryptoChallenge } from './crypto';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\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-bare': '>=13.0.0',\n '@magic-sdk/react-native-expo': false,\n '@magic-sdk/react-native': false,\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { provider, query, redirectURI } = await createURI.call(this, configuration);\n const url = `https://auth.magic.link/v1/oauth2/${provider}/start?${query}`;\n\n /**\n * Response Type Inspired by:\n * https://docs.expo.io/versions/latest/sdk/webbrowser/#returns\n */\n const res = await InAppBrowser.openAuth(url, redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n\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\nconst OAUTH_REDIRECT_METADATA_KEY = 'oauth_redirect_metadata';\n\nexport async function createURI(this: OAuthExtension, configuration: OAuthRedirectConfiguration) {\n // Bust any old, in-progress OAuth flows.\n await this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n // Unpack configuration, generate crypto values, and persist to storage.\n const { provider, redirectURI, scope, loginHint } = configuration;\n const { verifier, challenge, state } = await createCryptoChallenge();\n const bundleId = getBundleId();\n\n /* Stringify for RN Async storage */\n const storedData = JSON.stringify({\n verifier,\n state,\n });\n\n await this.utils.storage.setItem(OAUTH_REDIRECT_METADATA_KEY, storedData);\n\n // Formulate the initial redirect query to Magic's OAuth hub.\n // Required fields:\n // - `magic_api_key`\n // - `magic_challenge`\n // - `state`\n // - `redirect_uri`\n // - `platform`\n // Optional fields:\n // - `bundleId`\n\n const query = [\n `magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,\n `magic_challenge=${encodeURIComponent(challenge)}`,\n `state=${encodeURIComponent(state)}`,\n `platform=${encodeURIComponent('rn')}`,\n scope && `scope=${encodeURIComponent(scope.join(' '))}`,\n redirectURI && `redirect_uri=${encodeURIComponent(redirectURI)}`,\n loginHint && `login_hint=${encodeURIComponent(loginHint)}`,\n bundleId && `bundleId=${encodeURIComponent(bundleId)}`,\n ].reduce((prev, next) => (next ? `${prev}&${next}` : prev));\n\n return {\n query,\n provider,\n redirectURI,\n };\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const json: string = (await this.utils.storage.getItem(OAUTH_REDIRECT_METADATA_KEY)) as string;\n\n const { verifier, state } = JSON.parse(json);\n\n // Remove the save OAuth state from storage, it stays in memory now...\n this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.ParseRedirectResult, [\n queryString,\n verifier,\n state,\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 { WordArray } from 'crypto-js';\nimport sha256Fallback from 'crypto-js/sha256';\nimport Base64 from 'crypto-js/enc-base64';\n\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\nconst HAS_CRYPTO = typeof window !== 'undefined' && !!(window.crypto as any);\nconst HAS_SUBTLE_CRYPTO = HAS_CRYPTO && !!(window.crypto.subtle as any);\n\n/**\n * Stringifies `bytes` using the OAuth 2.0 `code_verifier` character set.\n */\nfunction bytesToVerifierString(bytes: Uint8Array) {\n return Array.from(bytes)\n .map((value: number) => CHARSET[value % CHARSET.length])\n .join('');\n}\n\n/**\n * Stringifies argument (as CryptoJS `WordArray` or EcmaScript `ArrayBuffer`)\n * and encodes to URL-safe Base64.\n */\nfunction base64URLEncodeFromByteArray(wordArray: WordArray): string;\nfunction base64URLEncodeFromByteArray(arrayBuffer: ArrayBuffer): string;\nfunction base64URLEncodeFromByteArray(arg: WordArray | ArrayBuffer): string {\n const makeURLSafe = (base64: string) => {\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n };\n\n if (arg instanceof ArrayBuffer) {\n const bytes = new Uint8Array(arg);\n const utf8Binary = Array.from(bytes)\n .map((value) => String.fromCharCode(value))\n .join('');\n\n const base64 = btoa(utf8Binary);\n return makeURLSafe(base64);\n }\n\n return makeURLSafe(Base64.stringify(arg));\n}\n\n/**\n * Produces a SHA-256 hash of the given `message`. This function first attempts\n * to use the browser's built-in `SubtleCrypto` API, falling back to\n * CryptoJS if required.\n */\nasync function sha256(message: string) {\n if (HAS_SUBTLE_CRYPTO) {\n const bytes = new TextEncoder().encode(message);\n return crypto.subtle.digest('SHA-256', bytes).then(base64URLEncodeFromByteArray);\n }\n\n return base64URLEncodeFromByteArray(sha256Fallback(message));\n}\n\n/**\n * Creates a cryptographically random string using the browser's built-in\n * `Crypto` API, falling back to `Math.random` if required.\n */\nfunction createRandomString(size: number) {\n const bytes = new Uint8Array(size);\n\n if (HAS_CRYPTO) {\n window.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < size; i += 1) bytes[i] = Math.floor(Math.random() * Math.floor(255));\n }\n\n return bytesToVerifierString(bytes);\n}\n\n/**\n * Creates OAuth 2.0-compatible `code_verifier`, `code_challenge`, and `state`\n * parameters.\n */\nexport async function createCryptoChallenge() {\n const state = createRandomString(128);\n const verifier = createRandomString(128);\n const challenge = await sha256(verifier);\n return { verifier, challenge, state };\n}\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n ParseRedirectResult = 'magic_oauth_parse_redirect_result',\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["InAppBrowser", "Extension", "getBundleId", "sha256Fallback", "Base64", "CHARSET", "HAS_CRYPTO", "HAS_SUBTLE_CRYPTO", "bytesToVerifierString", "bytes", "value", "base64URLEncodeFromByteArray", "arg", "makeURLSafe", "base64", "utf8Binary", "Base64", "sha256", "message", "__async", "sha256Fallback", "createRandomString", "size", "i", "createCryptoChallenge", "state", "verifier", "challenge", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "__async", "provider", "query", "redirectURI", "createURI", "url", "res", "InAppBrowser", "queryString", "getResult", "err", "OAUTH_REDIRECT_METADATA_KEY", "scope", "loginHint", "verifier", "challenge", "state", "createCryptoChallenge", "bundleId", "getBundleId", "storedData", "prev", "next", "_a", "json", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var p=(t,e,r)=>new Promise((u,a)=>{var s=i=>{try{c(r.next(i))}catch(n){a(n)}},d=i=>{try{c(r.throw(i))}catch(n){a(n)}},c=i=>i.done?u(i.value):Promise.resolve(i.value).then(s,d);c((r=r.apply(t,e)).next())});import{InAppBrowser as x}from"react-native-inappbrowser-reborn";import{Extension as E}from"@magic-sdk/react-native-bare";import{getBundleId as k}from"react-native-device-info";import v from"crypto-js/sha256";import _ from"crypto-js/enc-base64";var f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",R=typeof window!="undefined"&&!!window.crypto,U=R&&!!window.crypto.subtle;function O(t){return Array.from(t).map(e=>f[e%f.length]).join("")}function y(t){let e=r=>r.replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");if(t instanceof ArrayBuffer){let r=new Uint8Array(t),u=Array.from(r).map(s=>String.fromCharCode(s)).join(""),a=btoa(u);return e(a)}return e(_.stringify(t))}function w(t){return p(this,null,function*(){if(U){let e=new TextEncoder().encode(t);return crypto.subtle.digest("SHA-256",e).then(y)}return y(v(t))})}function h(t){let e=new Uint8Array(t);if(R)window.crypto.getRandomValues(e);else for(let r=0;r<t;r+=1)e[r]=Math.floor(Math.random()*Math.floor(255));return O(e)}function A(){return p(this,null,function*(){let t=h(128),e=h(128),r=yield w(e);return{verifier:e,challenge:r,state:t}})}var I=(e=>(e.ParseRedirectResult="magic_oauth_parse_redirect_result",e))(I||{}),C=(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))(C||{});var b=class extends E.Internal{constructor(){super(...arguments);this.name="oauth";this.config={};this.compat={"magic-sdk":!1,"@magic-sdk/react-native-bare":">=13.0.0","@magic-sdk/react-native-expo":!1,"@magic-sdk/react-native":!1}}loginWithPopup(r){return this.utils.createPromiEvent((u,a)=>p(this,null,function*(){try{let{provider:s,query:d,redirectURI:c}=yield D.call(this,r),i=`https://auth.magic.link/v1/oauth2/${s}/start?${d}`,n=yield x.openAuth(i,c,{});if(n.type==="success"){let l=new URL(n.url).search;u(P.call(this,l.toString()))}else a(this.createError(n.type,"User has cancelled the authentication",{}))}catch(s){a(this.createError(s.message,"An error has occurred",{err:s}))}}))}},g="oauth_redirect_metadata";function D(t){return p(this,null,function*(){yield this.utils.storage.removeItem(g);let{provider:e,redirectURI:r,scope:u,loginHint:a}=t,{verifier:s,challenge:d,state:c}=yield A(),i=k(),n=JSON.stringify({verifier:s,state:c});return yield this.utils.storage.setItem(g,n),{query:[`magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,`magic_challenge=${encodeURIComponent(d)}`,`state=${encodeURIComponent(c)}`,`platform=${encodeURIComponent("rn")}`,u&&`scope=${encodeURIComponent(u.join(" "))}`,r&&`redirect_uri=${encodeURIComponent(r)}`,a&&`login_hint=${encodeURIComponent(a)}`,i&&`bundleId=${encodeURIComponent(i)}`].reduce((o,m)=>m?`${o}&${m}`:o),provider:e,redirectURI:r}})}function P(t){return this.utils.createPromiEvent((e,r)=>p(this,null,function*(){var l;let u=yield this.utils.storage.getItem(g),{verifier:a,state:s}=JSON.parse(u);this.utils.storage.removeItem(g);let d=this.utils.createJsonRpcRequestPayload("magic_oauth_parse_redirect_result",[t,a,s]),c=yield this.request(d),i=c,n=c;n.error&&r(this.createError(n.error,(l=n.error_description)!=null?l:"An error occurred.",{errorURI:n.error_uri,provider:n.provider})),e(i)}))}export{C as OAuthErrorCode,b as OAuthExtension,I as OAuthPayloadMethods,D as createURI,P as getResult};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/index.ts", "../../src/crypto.ts", "../../src/types.ts"],
|
|
4
|
+
"sourcesContent": ["import { InAppBrowser } from 'react-native-inappbrowser-reborn';\nimport { Extension } from '@magic-sdk/react-native-bare';\nimport { getBundleId } from 'react-native-device-info';\nimport { createCryptoChallenge } from './crypto';\nimport {\n OAuthErrorData,\n OAuthPayloadMethods,\n OAuthRedirectConfiguration,\n OAuthRedirectError,\n OAuthRedirectResult,\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-bare': '>=13.0.0',\n '@magic-sdk/react-native-expo': false,\n '@magic-sdk/react-native': false,\n };\n\n public loginWithPopup(configuration: OAuthRedirectConfiguration) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n try {\n const { provider, query, redirectURI } = await createURI.call(this, configuration);\n const url = `https://auth.magic.link/v1/oauth2/${provider}/start?${query}`;\n\n /**\n * Response Type Inspired by:\n * https://docs.expo.io/versions/latest/sdk/webbrowser/#returns\n */\n const res = await InAppBrowser.openAuth(url, redirectURI, {});\n\n if (res.type === 'success') {\n const queryString = new URL(res.url).search;\n\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\nconst OAUTH_REDIRECT_METADATA_KEY = 'oauth_redirect_metadata';\n\nexport async function createURI(this: OAuthExtension, configuration: OAuthRedirectConfiguration) {\n // Bust any old, in-progress OAuth flows.\n await this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n // Unpack configuration, generate crypto values, and persist to storage.\n const { provider, redirectURI, scope, loginHint } = configuration;\n const { verifier, challenge, state } = await createCryptoChallenge();\n const bundleId = getBundleId();\n\n /* Stringify for RN Async storage */\n const storedData = JSON.stringify({\n verifier,\n state,\n });\n\n await this.utils.storage.setItem(OAUTH_REDIRECT_METADATA_KEY, storedData);\n\n // Formulate the initial redirect query to Magic's OAuth hub.\n // Required fields:\n // - `magic_api_key`\n // - `magic_challenge`\n // - `state`\n // - `redirect_uri`\n // - `platform`\n // Optional fields:\n // - `bundleId`\n\n const query = [\n `magic_api_key=${encodeURIComponent(this.sdk.apiKey)}`,\n `magic_challenge=${encodeURIComponent(challenge)}`,\n `state=${encodeURIComponent(state)}`,\n `platform=${encodeURIComponent('rn')}`,\n scope && `scope=${encodeURIComponent(scope.join(' '))}`,\n redirectURI && `redirect_uri=${encodeURIComponent(redirectURI)}`,\n loginHint && `login_hint=${encodeURIComponent(loginHint)}`,\n bundleId && `bundleId=${encodeURIComponent(bundleId)}`,\n ].reduce((prev, next) => (next ? `${prev}&${next}` : prev));\n\n return {\n query,\n provider,\n redirectURI,\n };\n}\n\nexport function getResult(this: OAuthExtension, queryString: string) {\n return this.utils.createPromiEvent<OAuthRedirectResult>(async (resolve, reject) => {\n const json: string = (await this.utils.storage.getItem(OAUTH_REDIRECT_METADATA_KEY)) as string;\n\n const { verifier, state } = JSON.parse(json);\n\n // Remove the save OAuth state from storage, it stays in memory now...\n this.utils.storage.removeItem(OAUTH_REDIRECT_METADATA_KEY);\n\n const parseRedirectResult = this.utils.createJsonRpcRequestPayload(OAuthPayloadMethods.ParseRedirectResult, [\n queryString,\n verifier,\n state,\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 { WordArray } from 'crypto-js';\nimport sha256Fallback from 'crypto-js/sha256';\nimport Base64 from 'crypto-js/enc-base64';\n\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';\nconst HAS_CRYPTO = typeof window !== 'undefined' && !!(window.crypto as any);\nconst HAS_SUBTLE_CRYPTO = HAS_CRYPTO && !!(window.crypto.subtle as any);\n\n/**\n * Stringifies `bytes` using the OAuth 2.0 `code_verifier` character set.\n */\nfunction bytesToVerifierString(bytes: Uint8Array) {\n return Array.from(bytes)\n .map((value: number) => CHARSET[value % CHARSET.length])\n .join('');\n}\n\n/**\n * Stringifies argument (as CryptoJS `WordArray` or EcmaScript `ArrayBuffer`)\n * and encodes to URL-safe Base64.\n */\nfunction base64URLEncodeFromByteArray(wordArray: WordArray): string;\nfunction base64URLEncodeFromByteArray(arrayBuffer: ArrayBuffer): string;\nfunction base64URLEncodeFromByteArray(arg: WordArray | ArrayBuffer): string {\n const makeURLSafe = (base64: string) => {\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n };\n\n if (arg instanceof ArrayBuffer) {\n const bytes = new Uint8Array(arg);\n const utf8Binary = Array.from(bytes)\n .map((value) => String.fromCharCode(value))\n .join('');\n\n const base64 = btoa(utf8Binary);\n return makeURLSafe(base64);\n }\n\n return makeURLSafe(Base64.stringify(arg));\n}\n\n/**\n * Produces a SHA-256 hash of the given `message`. This function first attempts\n * to use the browser's built-in `SubtleCrypto` API, falling back to\n * CryptoJS if required.\n */\nasync function sha256(message: string) {\n if (HAS_SUBTLE_CRYPTO) {\n const bytes = new TextEncoder().encode(message);\n return crypto.subtle.digest('SHA-256', bytes).then(base64URLEncodeFromByteArray);\n }\n\n return base64URLEncodeFromByteArray(sha256Fallback(message));\n}\n\n/**\n * Creates a cryptographically random string using the browser's built-in\n * `Crypto` API, falling back to `Math.random` if required.\n */\nfunction createRandomString(size: number) {\n const bytes = new Uint8Array(size);\n\n if (HAS_CRYPTO) {\n window.crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < size; i += 1) bytes[i] = Math.floor(Math.random() * Math.floor(255));\n }\n\n return bytesToVerifierString(bytes);\n}\n\n/**\n * Creates OAuth 2.0-compatible `code_verifier`, `code_challenge`, and `state`\n * parameters.\n */\nexport async function createCryptoChallenge() {\n const state = createRandomString(128);\n const verifier = createRandomString(128);\n const challenge = await sha256(verifier);\n return { verifier, challenge, state };\n}\n", "import { MagicUserMetadata } from '@magic-sdk/types';\n\nexport enum OAuthPayloadMethods {\n ParseRedirectResult = 'magic_oauth_parse_redirect_result',\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"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["InAppBrowser", "Extension", "getBundleId", "sha256Fallback", "Base64", "CHARSET", "HAS_CRYPTO", "HAS_SUBTLE_CRYPTO", "bytesToVerifierString", "bytes", "value", "base64URLEncodeFromByteArray", "arg", "makeURLSafe", "base64", "utf8Binary", "Base64", "sha256", "message", "__async", "sha256Fallback", "createRandomString", "size", "i", "createCryptoChallenge", "state", "verifier", "challenge", "OAuthPayloadMethods", "OAuthErrorCode", "OAuthExtension", "Extension", "configuration", "resolve", "reject", "__async", "provider", "query", "redirectURI", "createURI", "url", "res", "InAppBrowser", "queryString", "getResult", "err", "OAUTH_REDIRECT_METADATA_KEY", "scope", "loginHint", "verifier", "challenge", "state", "createCryptoChallenge", "bundleId", "getBundleId", "storedData", "prev", "next", "_a", "json", "parseRedirectResult", "resultOrError", "maybeResult", "maybeError"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Extension } from '@magic-sdk/react-native-bare';
|
|
2
|
+
import { OAuthRedirectConfiguration, OAuthRedirectResult } from './types';
|
|
3
|
+
export declare class OAuthExtension extends Extension.Internal<'oauth'> {
|
|
4
|
+
name: "oauth";
|
|
5
|
+
config: {};
|
|
6
|
+
compat: {
|
|
7
|
+
'magic-sdk': boolean;
|
|
8
|
+
'@magic-sdk/react-native-bare': string;
|
|
9
|
+
'@magic-sdk/react-native-expo': boolean;
|
|
10
|
+
'@magic-sdk/react-native': boolean;
|
|
11
|
+
};
|
|
12
|
+
loginWithPopup(configuration: OAuthRedirectConfiguration): import("@magic-sdk/react-native-bare").PromiEvent<OAuthRedirectResult, {
|
|
13
|
+
done: (result: OAuthRedirectResult) => void;
|
|
14
|
+
error: (reason: any) => void;
|
|
15
|
+
settled: () => void;
|
|
16
|
+
}>;
|
|
17
|
+
}
|
|
18
|
+
export declare function createURI(this: OAuthExtension, configuration: OAuthRedirectConfiguration): Promise<{
|
|
19
|
+
query: string | undefined;
|
|
20
|
+
provider: import("./types").OAuthProvider;
|
|
21
|
+
redirectURI: string;
|
|
22
|
+
}>;
|
|
23
|
+
export declare function getResult(this: OAuthExtension, queryString: string): import("@magic-sdk/react-native-bare").PromiEvent<OAuthRedirectResult, {
|
|
24
|
+
done: (result: OAuthRedirectResult) => void;
|
|
25
|
+
error: (reason: any) => void;
|
|
26
|
+
settled: () => void;
|
|
27
|
+
}>;
|
|
28
|
+
export * from './types';
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { MagicUserMetadata } from '@magic-sdk/types';
|
|
2
|
+
export declare enum OAuthPayloadMethods {
|
|
3
|
+
ParseRedirectResult = "magic_oauth_parse_redirect_result"
|
|
4
|
+
}
|
|
5
|
+
export declare type OAuthProvider = 'google' | 'facebook' | 'apple' | 'github' | 'bitbucket' | 'gitlab' | 'linkedin' | 'twitter' | 'discord' | 'twitch' | 'microsoft';
|
|
6
|
+
export interface OAuthErrorData {
|
|
7
|
+
provider: OAuthProvider;
|
|
8
|
+
errorURI?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface OpenIDConnectProfile {
|
|
11
|
+
name?: string;
|
|
12
|
+
familyName?: string;
|
|
13
|
+
givenName?: string;
|
|
14
|
+
middleName?: string;
|
|
15
|
+
nickname?: string;
|
|
16
|
+
preferredUsername?: string;
|
|
17
|
+
profile?: string;
|
|
18
|
+
picture?: string;
|
|
19
|
+
website?: string;
|
|
20
|
+
gender?: string;
|
|
21
|
+
birthdate?: string;
|
|
22
|
+
zoneinfo?: string;
|
|
23
|
+
locale?: string;
|
|
24
|
+
updatedAt?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface OpenIDConnectEmail {
|
|
27
|
+
email?: string;
|
|
28
|
+
emailVerified?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface OpenIDConnectPhone {
|
|
31
|
+
phoneNumber?: string;
|
|
32
|
+
phoneNumberVerified?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface OpenIDConnectAddress {
|
|
35
|
+
address?: {
|
|
36
|
+
formatted?: string;
|
|
37
|
+
streetAddress?: string;
|
|
38
|
+
locality?: string;
|
|
39
|
+
region?: string;
|
|
40
|
+
postalCode?: string;
|
|
41
|
+
country?: string;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export declare type OpenIDConnectUserInfo = OpenIDConnectProfile & OpenIDConnectEmail & OpenIDConnectPhone & OpenIDConnectAddress & {
|
|
45
|
+
sub?: string;
|
|
46
|
+
sources?: Record<string, any>;
|
|
47
|
+
} & Record<string, any>;
|
|
48
|
+
export interface OAuthRedirectResult {
|
|
49
|
+
oauth: {
|
|
50
|
+
provider: OAuthProvider;
|
|
51
|
+
scope: string[];
|
|
52
|
+
accessToken: string;
|
|
53
|
+
userHandle: string;
|
|
54
|
+
userInfo: OpenIDConnectUserInfo;
|
|
55
|
+
};
|
|
56
|
+
magic: {
|
|
57
|
+
idToken: string;
|
|
58
|
+
userMetadata: MagicUserMetadata;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export interface OAuthRedirectError {
|
|
62
|
+
provider: OAuthProvider;
|
|
63
|
+
error: string;
|
|
64
|
+
error_description?: string;
|
|
65
|
+
error_uri?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface OAuthRedirectConfiguration {
|
|
68
|
+
provider: OAuthProvider;
|
|
69
|
+
redirectURI: string;
|
|
70
|
+
scope?: string[];
|
|
71
|
+
loginHint?: string;
|
|
72
|
+
}
|
|
73
|
+
export declare enum OAuthErrorCode {
|
|
74
|
+
InvalidRequest = "invalid_request",
|
|
75
|
+
InvalidClient = "invalid_client",
|
|
76
|
+
InvalidScope = "invalid_scope",
|
|
77
|
+
InvalidGrant = "invalid_grant",
|
|
78
|
+
UnauthorizedClient = "unauthorized_client",
|
|
79
|
+
UnsupportedResponseType = "unsupported_response_type",
|
|
80
|
+
UnsupportedGrantType = "unsupported_grant_type",
|
|
81
|
+
UnsupportedTokenType = "unsupported_token_type",
|
|
82
|
+
AccessDenied = "access_denied",
|
|
83
|
+
ServerError = "server_error",
|
|
84
|
+
TemporarilyUnavailable = "temporarily_unavailable"
|
|
85
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@magic-ext/react-native-bare-oauth",
|
|
3
|
+
"version": "7.0.0",
|
|
4
|
+
"description": "Magic SDK OAuth Extension for Bare React Native environments.",
|
|
5
|
+
"author": "Magic <team@magic.link> (https://magic.link/)",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/magiclabs/magic-js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"target": "node",
|
|
15
|
+
"main": "./dist/cjs/index.js",
|
|
16
|
+
"module": "./dist/es/index.js",
|
|
17
|
+
"types": "./dist/types/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
"import": "./dist/es/index.mjs",
|
|
20
|
+
"require": "./dist/cjs/index.js"
|
|
21
|
+
},
|
|
22
|
+
"externals": {
|
|
23
|
+
"include": [
|
|
24
|
+
"@magic-sdk/react-native-bare"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@magic-sdk/types": "^10.0.1",
|
|
29
|
+
"crypto-js": "^3.3.0",
|
|
30
|
+
"react-native-device-info": "^10.3.0",
|
|
31
|
+
"react-native-inappbrowser-reborn": "^3.7.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@magic-sdk/react-native-bare": "^13.0.1",
|
|
35
|
+
"@types/crypto-js": "~3.1.47"
|
|
36
|
+
},
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@magic-sdk/react-native-bare": ">=13.0.0"
|
|
39
|
+
}
|
|
40
|
+
}
|