expo-auth-session 3.2.2 → 3.4.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/CHANGELOG.md +20 -0
- package/README.md +1 -1
- package/build/AuthRequest.js +16 -1
- package/build/AuthRequest.js.map +1 -1
- package/build/AuthRequestHooks.js +9 -5
- package/build/AuthRequestHooks.js.map +1 -1
- package/build/AuthSession.d.ts +1 -1
- package/build/AuthSession.js +1 -1
- package/build/AuthSession.js.map +1 -1
- package/build/Errors.d.ts +1 -1
- package/build/Errors.js +20 -1
- package/build/Errors.js.map +1 -1
- package/build/Fetch.js +1 -1
- package/build/Fetch.js.map +1 -1
- package/build/PKCE.js +1 -4
- package/build/PKCE.js.map +1 -1
- package/build/QueryParams.js.map +1 -1
- package/build/SessionUrlProvider.js +10 -6
- package/build/SessionUrlProvider.js.map +1 -1
- package/build/TokenRequest.js +31 -10
- package/build/TokenRequest.js.map +1 -1
- package/build/providers/Facebook.js +1 -0
- package/build/providers/Facebook.js.map +1 -1
- package/build/providers/Google.js +6 -4
- package/build/providers/Google.js.map +1 -1
- package/build/providers/ProviderUtils.js +1 -3
- package/build/providers/ProviderUtils.js.map +1 -1
- package/package.json +7 -7
- package/src/AuthRequestHooks.ts +13 -5
- package/src/AuthSession.ts +1 -1
- package/src/Errors.ts +1 -1
- package/src/Fetch.ts +1 -1
- package/src/PKCE.ts +1 -4
- package/src/QueryParams.ts +4 -3
- package/src/SessionUrlProvider.ts +11 -5
- package/src/TokenRequest.ts +12 -6
- package/src/providers/Google.ts +4 -4
- package/src/providers/ProviderUtils.ts +4 -3
package/build/TokenRequest.js
CHANGED
|
@@ -16,16 +16,6 @@ export function getCurrentTimeInSeconds() {
|
|
|
16
16
|
* [Section 5.1](https://tools.ietf.org/html/rfc6749#section-5.1)
|
|
17
17
|
*/
|
|
18
18
|
export class TokenResponse {
|
|
19
|
-
constructor(response) {
|
|
20
|
-
this.accessToken = response.accessToken;
|
|
21
|
-
this.tokenType = response.tokenType ?? 'bearer';
|
|
22
|
-
this.expiresIn = response.expiresIn;
|
|
23
|
-
this.refreshToken = response.refreshToken;
|
|
24
|
-
this.scope = response.scope;
|
|
25
|
-
this.state = response.state;
|
|
26
|
-
this.idToken = response.idToken;
|
|
27
|
-
this.issuedAt = response.issuedAt ?? getCurrentTimeInSeconds();
|
|
28
|
-
}
|
|
29
19
|
/**
|
|
30
20
|
* Determines whether a token refresh request must be made to refresh the tokens
|
|
31
21
|
*
|
|
@@ -67,6 +57,24 @@ export class TokenResponse {
|
|
|
67
57
|
issuedAt: params.issued_at,
|
|
68
58
|
});
|
|
69
59
|
}
|
|
60
|
+
accessToken;
|
|
61
|
+
tokenType;
|
|
62
|
+
expiresIn;
|
|
63
|
+
refreshToken;
|
|
64
|
+
scope;
|
|
65
|
+
state;
|
|
66
|
+
idToken;
|
|
67
|
+
issuedAt;
|
|
68
|
+
constructor(response) {
|
|
69
|
+
this.accessToken = response.accessToken;
|
|
70
|
+
this.tokenType = response.tokenType ?? 'bearer';
|
|
71
|
+
this.expiresIn = response.expiresIn;
|
|
72
|
+
this.refreshToken = response.refreshToken;
|
|
73
|
+
this.scope = response.scope;
|
|
74
|
+
this.state = response.state;
|
|
75
|
+
this.idToken = response.idToken;
|
|
76
|
+
this.issuedAt = response.issuedAt ?? getCurrentTimeInSeconds();
|
|
77
|
+
}
|
|
70
78
|
applyResponseConfig(response) {
|
|
71
79
|
this.accessToken = response.accessToken ?? this.accessToken;
|
|
72
80
|
this.tokenType = response.tokenType ?? this.tokenType ?? 'bearer';
|
|
@@ -107,6 +115,7 @@ export class TokenResponse {
|
|
|
107
115
|
}
|
|
108
116
|
}
|
|
109
117
|
class Request {
|
|
118
|
+
request;
|
|
110
119
|
constructor(request) {
|
|
111
120
|
this.request = request;
|
|
112
121
|
}
|
|
@@ -124,6 +133,11 @@ class Request {
|
|
|
124
133
|
* A generic token request.
|
|
125
134
|
*/
|
|
126
135
|
class TokenRequest extends Request {
|
|
136
|
+
grantType;
|
|
137
|
+
clientId;
|
|
138
|
+
clientSecret;
|
|
139
|
+
scopes;
|
|
140
|
+
extraParams;
|
|
127
141
|
constructor(request, grantType) {
|
|
128
142
|
super(request);
|
|
129
143
|
this.grantType = grantType;
|
|
@@ -194,6 +208,8 @@ class TokenRequest extends Request {
|
|
|
194
208
|
* [Section 4.1.3](https://tools.ietf.org/html/rfc6749#section-4.1.3)
|
|
195
209
|
*/
|
|
196
210
|
export class AccessTokenRequest extends TokenRequest {
|
|
211
|
+
code;
|
|
212
|
+
redirectUri;
|
|
197
213
|
constructor(options) {
|
|
198
214
|
invariant(options.redirectUri, `\`AccessTokenRequest\` requires a valid \`redirectUri\` (it must also match the one used in the auth request). Example: ${Platform.select({
|
|
199
215
|
web: 'https://yourwebsite.com/redirect',
|
|
@@ -232,6 +248,7 @@ export class AccessTokenRequest extends TokenRequest {
|
|
|
232
248
|
* [Section 6](https://tools.ietf.org/html/rfc6749#section-6)
|
|
233
249
|
*/
|
|
234
250
|
export class RefreshTokenRequest extends TokenRequest {
|
|
251
|
+
refreshToken;
|
|
235
252
|
constructor(options) {
|
|
236
253
|
invariant(options.refreshToken, `\`RefreshTokenRequest\` requires a valid \`refreshToken\`.`);
|
|
237
254
|
super(options, GrantType.RefreshToken);
|
|
@@ -261,6 +278,10 @@ export class RefreshTokenRequest extends TokenRequest {
|
|
|
261
278
|
* [Section 2.1](https://tools.ietf.org/html/rfc7009#section-2.1)
|
|
262
279
|
*/
|
|
263
280
|
export class RevokeTokenRequest extends Request {
|
|
281
|
+
clientId;
|
|
282
|
+
clientSecret;
|
|
283
|
+
token;
|
|
284
|
+
tokenTypeHint;
|
|
264
285
|
constructor(request) {
|
|
265
286
|
super(request);
|
|
266
287
|
invariant(request.token, `\`RevokeTokenRequest\` requires a valid \`token\` to revoke.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TokenRequest.js","sourceRoot":"","sources":["../src/TokenRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import invariant from 'invariant';\nimport { Platform } from 'react-native';\n\nimport * as Base64 from './Base64';\nimport * as ServiceConfig from './Discovery';\nimport { ResponseErrorConfig, TokenError } from './Errors';\nimport { Headers, requestAsync } from './Fetch';\nimport {\n AccessTokenRequestConfig,\n GrantType,\n RefreshTokenRequestConfig,\n RevokeTokenRequestConfig,\n ServerTokenResponseConfig,\n TokenRequestConfig,\n TokenResponseConfig,\n TokenType,\n TokenTypeHint,\n} from './TokenRequest.types';\n\n/**\n * Returns the current time in seconds.\n */\nexport function getCurrentTimeInSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n\n/**\n * Token Response.\n *\n * [Section 5.1](https://tools.ietf.org/html/rfc6749#section-5.1)\n */\nexport class TokenResponse implements TokenResponseConfig {\n /**\n * Determines whether a token refresh request must be made to refresh the tokens\n *\n * @param token\n * @param secondsMargin\n */\n static isTokenFresh(\n token: Pick<TokenResponse, 'expiresIn' | 'issuedAt'>,\n /**\n * -10 minutes in seconds\n */\n secondsMargin: number = 60 * 10 * -1\n ): boolean {\n if (!token) {\n return false;\n }\n if (token.expiresIn) {\n const now = getCurrentTimeInSeconds();\n return now < token.issuedAt + token.expiresIn + secondsMargin;\n }\n // if there is no expiration time but we have an access token, it is assumed to never expire\n return true;\n }\n /**\n * Creates a `TokenResponse` from query parameters returned from an `AuthRequest`.\n *\n * @param params\n */\n static fromQueryParams(params: Record<string, string>): TokenResponse {\n return new TokenResponse({\n accessToken: params.access_token,\n refreshToken: params.refresh_token,\n scope: params.scope,\n state: params.state,\n idToken: params.id_token,\n // @ts-ignore: Expected specific string\n tokenType: params.token_type,\n // @ts-ignore: Expected number\n expiresIn: params.expires_in,\n // @ts-ignore: Expected number\n issuedAt: params.issued_at,\n });\n }\n\n accessToken: string;\n tokenType: TokenType;\n expiresIn?: number;\n refreshToken?: string;\n scope?: string;\n state?: string;\n idToken?: string;\n issuedAt: number;\n\n constructor(response: TokenResponseConfig) {\n this.accessToken = response.accessToken;\n this.tokenType = response.tokenType ?? 'bearer';\n this.expiresIn = response.expiresIn;\n this.refreshToken = response.refreshToken;\n this.scope = response.scope;\n this.state = response.state;\n this.idToken = response.idToken;\n this.issuedAt = response.issuedAt ?? getCurrentTimeInSeconds();\n }\n\n private applyResponseConfig(response: TokenResponseConfig) {\n this.accessToken = response.accessToken ?? this.accessToken;\n this.tokenType = response.tokenType ?? this.tokenType ?? 'bearer';\n this.expiresIn = response.expiresIn ?? this.expiresIn;\n this.refreshToken = response.refreshToken ?? this.refreshToken;\n this.scope = response.scope ?? this.scope;\n this.state = response.state ?? this.state;\n this.idToken = response.idToken ?? this.idToken;\n this.issuedAt = response.issuedAt ?? this.issuedAt ?? getCurrentTimeInSeconds();\n }\n\n getRequestConfig(): TokenResponseConfig {\n return {\n accessToken: this.accessToken,\n idToken: this.idToken,\n refreshToken: this.refreshToken,\n scope: this.scope,\n state: this.state,\n tokenType: this.tokenType,\n issuedAt: this.issuedAt,\n expiresIn: this.expiresIn,\n };\n }\n\n async refreshAsync(\n config: Omit<TokenRequestConfig, 'grantType' | 'refreshToken'>,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n ): Promise<TokenResponse> {\n const request = new RefreshTokenRequest({\n ...config,\n refreshToken: this.refreshToken,\n });\n const response = await request.performAsync(discovery);\n // Custom: reuse the refresh token if one wasn't returned\n response.refreshToken = response.refreshToken ?? this.refreshToken;\n const json = response.getRequestConfig();\n this.applyResponseConfig(json);\n return this;\n }\n\n shouldRefresh(): boolean {\n // no refresh token available and token has expired\n return !(TokenResponse.isTokenFresh(this) || !this.refreshToken);\n }\n}\n\nclass Request<T, B> {\n constructor(protected request: T) {}\n\n async performAsync(discovery: ServiceConfig.DiscoveryDocument): Promise<B> {\n throw new Error('performAsync must be extended');\n }\n\n getRequestConfig(): T {\n throw new Error('getRequestConfig must be extended');\n }\n\n getQueryBody(): Record<string, string> {\n throw new Error('getQueryBody must be extended');\n }\n}\n\n/**\n * A generic token request.\n */\nclass TokenRequest<T extends TokenRequestConfig> extends Request<T, TokenResponse> {\n readonly clientId: string;\n readonly clientSecret?: string;\n readonly scopes?: string[];\n readonly extraParams?: Record<string, string>;\n\n constructor(request, public grantType: GrantType) {\n super(request);\n this.clientId = request.clientId;\n this.clientSecret = request.clientSecret;\n this.extraParams = request.extraParams;\n this.scopes = request.scopes;\n }\n\n getHeaders(): Headers {\n const headers: Headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n if (typeof this.clientSecret !== 'undefined') {\n // If client secret exists, it should be converted to base64\n // https://tools.ietf.org/html/rfc6749#section-2.3.1\n const encodedClientId = encodeURIComponent(this.clientId);\n const encodedClientSecret = encodeURIComponent(this.clientSecret);\n const credentials = `${encodedClientId}:${encodedClientSecret}`;\n const basicAuth = Base64.encodeNoWrap(credentials);\n headers.Authorization = `Basic ${basicAuth}`;\n }\n\n return headers;\n }\n\n async performAsync(discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>) {\n // redirect URI must not be nil\n invariant(\n discovery.tokenEndpoint,\n `Cannot invoke \\`performAsync()\\` without a valid tokenEndpoint`\n );\n const response = await requestAsync<ServerTokenResponseConfig | ResponseErrorConfig>(\n discovery.tokenEndpoint,\n {\n dataType: 'json',\n method: 'POST',\n headers: this.getHeaders(),\n body: this.getQueryBody(),\n }\n );\n\n if ('error' in response) {\n throw new TokenError(response);\n }\n\n return new TokenResponse({\n accessToken: response.access_token,\n tokenType: response.token_type,\n expiresIn: response.expires_in,\n refreshToken: response.refresh_token,\n scope: response.scope,\n idToken: response.id_token,\n issuedAt: response.issued_at,\n });\n }\n\n getQueryBody() {\n const queryBody: Record<string, string> = {\n grant_type: this.grantType,\n };\n\n if (!this.clientSecret) {\n // Only add the client ID if client secret is not present, otherwise pass the client id with the secret in the request body.\n queryBody.client_id = this.clientId;\n }\n\n if (this.scopes) {\n queryBody.scope = this.scopes.join(' ');\n }\n\n if (this.extraParams) {\n for (const extra in this.extraParams) {\n if (extra in this.extraParams && !(extra in queryBody)) {\n queryBody[extra] = this.extraParams[extra];\n }\n }\n }\n return queryBody;\n }\n}\n\n/**\n * Access token request. Exchange an authorization code for a user access token.\n *\n * [Section 4.1.3](https://tools.ietf.org/html/rfc6749#section-4.1.3)\n */\nexport class AccessTokenRequest extends TokenRequest<AccessTokenRequestConfig>\n implements AccessTokenRequestConfig {\n readonly code: string;\n readonly redirectUri: string;\n\n constructor(options: AccessTokenRequestConfig) {\n invariant(\n options.redirectUri,\n `\\`AccessTokenRequest\\` requires a valid \\`redirectUri\\` (it must also match the one used in the auth request). Example: ${Platform.select(\n {\n web: 'https://yourwebsite.com/redirect',\n default: 'myapp://redirect',\n }\n )}`\n );\n\n invariant(\n options.code,\n `\\`AccessTokenRequest\\` requires a valid authorization \\`code\\`. This is what's received from the authorization server after an auth request.`\n );\n super(options, GrantType.AuthorizationCode);\n this.code = options.code;\n this.redirectUri = options.redirectUri;\n }\n\n getQueryBody() {\n const queryBody: Record<string, string> = super.getQueryBody();\n\n if (this.redirectUri) {\n queryBody.redirect_uri = this.redirectUri;\n }\n\n if (this.code) {\n queryBody.code = this.code;\n }\n\n return queryBody;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n grantType: this.grantType,\n code: this.code,\n redirectUri: this.redirectUri,\n extraParams: this.extraParams,\n scopes: this.scopes,\n };\n }\n}\n\n/**\n * Refresh request.\n *\n * [Section 6](https://tools.ietf.org/html/rfc6749#section-6)\n */\nexport class RefreshTokenRequest extends TokenRequest<RefreshTokenRequestConfig>\n implements RefreshTokenRequestConfig {\n readonly refreshToken?: string;\n\n constructor(options: RefreshTokenRequestConfig) {\n invariant(options.refreshToken, `\\`RefreshTokenRequest\\` requires a valid \\`refreshToken\\`.`);\n super(options, GrantType.RefreshToken);\n this.refreshToken = options.refreshToken;\n }\n\n getQueryBody() {\n const queryBody = super.getQueryBody();\n\n if (this.refreshToken) {\n queryBody.refresh_token = this.refreshToken;\n }\n\n return queryBody;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n grantType: this.grantType,\n refreshToken: this.refreshToken,\n extraParams: this.extraParams,\n scopes: this.scopes,\n };\n }\n}\n\n/**\n * Revocation request for a given token.\n *\n * [Section 2.1](https://tools.ietf.org/html/rfc7009#section-2.1)\n */\nexport class RevokeTokenRequest extends Request<RevokeTokenRequestConfig, boolean>\n implements RevokeTokenRequestConfig {\n readonly clientId?: string;\n readonly clientSecret?: string;\n readonly token: string;\n readonly tokenTypeHint?: TokenTypeHint;\n\n constructor(request: RevokeTokenRequestConfig) {\n super(request);\n invariant(request.token, `\\`RevokeTokenRequest\\` requires a valid \\`token\\` to revoke.`);\n this.clientId = request.clientId;\n this.clientSecret = request.clientSecret;\n this.token = request.token;\n this.tokenTypeHint = request.tokenTypeHint;\n }\n\n getHeaders(): Headers {\n const headers: Headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n if (typeof this.clientSecret !== 'undefined' && this.clientId) {\n // If client secret exists, it should be converted to base64\n // https://tools.ietf.org/html/rfc6749#section-2.3.1\n const encodedClientId = encodeURIComponent(this.clientId);\n const encodedClientSecret = encodeURIComponent(this.clientSecret);\n const credentials = `${encodedClientId}:${encodedClientSecret}`;\n const basicAuth = Base64.encodeNoWrap(credentials);\n headers.Authorization = `Basic ${basicAuth}`;\n }\n\n return headers;\n }\n\n /**\n * Perform a token revocation request.\n *\n * @param discovery The `revocationEndpoint` for a provider.\n */\n async performAsync(discovery: Pick<ServiceConfig.DiscoveryDocument, 'revocationEndpoint'>) {\n invariant(\n discovery.revocationEndpoint,\n `Cannot invoke \\`performAsync()\\` without a valid revocationEndpoint`\n );\n await requestAsync<boolean>(discovery.revocationEndpoint, {\n method: 'POST',\n headers: this.getHeaders(),\n body: this.getQueryBody(),\n });\n\n return true;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n token: this.token,\n tokenTypeHint: this.tokenTypeHint,\n };\n }\n\n getQueryBody(): Record<string, string> {\n const queryBody: Record<string, string> = { token: this.token };\n if (this.tokenTypeHint) {\n queryBody.token_type_hint = this.tokenTypeHint;\n }\n // Include client creds https://tools.ietf.org/html/rfc6749#section-2.3.1\n if (this.clientId) {\n queryBody.client_id = this.clientId;\n }\n if (this.clientSecret) {\n queryBody.client_secret = this.clientSecret;\n }\n return queryBody;\n }\n}\n\n/**\n * Exchange an auth code for an access token that can be used to get data from the provider.\n *\n * @param config\n * @param discovery The `tokenEndpoint` for a provider.\n */\nexport function exchangeCodeAsync(\n config: AccessTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n): Promise<TokenResponse> {\n const request = new AccessTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Refresh an access token. Often this just requires the `refreshToken` and `scopes` parameters.\n *\n * [Section 6](https://tools.ietf.org/html/rfc6749#section-6)\n *\n * @param config\n * @param discovery The `tokenEndpoint` for a provider.\n */\nexport function refreshAsync(\n config: RefreshTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n): Promise<TokenResponse> {\n const request = new RefreshTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Revoke a token with a provider.\n * This makes the token unusable, effectively requiring the user to login again.\n *\n * @param config\n * @param discovery The `revocationEndpoint` for a provider.\n */\nexport function revokeAsync(\n config: RevokeTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'revocationEndpoint'>\n): Promise<boolean> {\n const request = new RevokeTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Fetch generic user info from the provider's OpenID Connect `userInfoEndpoint` (if supported).\n *\n * [UserInfo](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\n *\n * @param config The `accessToken` for a user, returned from a code exchange or auth request.\n * @param discovery The `userInfoEndpoint` for a provider.\n */\nexport function fetchUserInfoAsync(\n config: Pick<TokenResponse, 'accessToken'>,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'userInfoEndpoint'>\n): Promise<Record<string, any>> {\n if (!discovery.userInfoEndpoint) {\n throw new Error('User info endpoint is not defined in the service config discovery document');\n }\n return requestAsync<Record<string, any>>(discovery.userInfoEndpoint, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Bearer ${config.accessToken}`,\n },\n dataType: 'json',\n method: 'GET',\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TokenRequest.js","sourceRoot":"","sources":["../src/TokenRequest.ts"],"names":[],"mappings":"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","sourcesContent":["import invariant from 'invariant';\nimport { Platform } from 'react-native';\n\nimport * as Base64 from './Base64';\nimport * as ServiceConfig from './Discovery';\nimport { ResponseErrorConfig, TokenError } from './Errors';\nimport { Headers, requestAsync } from './Fetch';\nimport {\n AccessTokenRequestConfig,\n GrantType,\n RefreshTokenRequestConfig,\n RevokeTokenRequestConfig,\n ServerTokenResponseConfig,\n TokenRequestConfig,\n TokenResponseConfig,\n TokenType,\n TokenTypeHint,\n} from './TokenRequest.types';\n\n/**\n * Returns the current time in seconds.\n */\nexport function getCurrentTimeInSeconds(): number {\n return Math.floor(Date.now() / 1000);\n}\n\n/**\n * Token Response.\n *\n * [Section 5.1](https://tools.ietf.org/html/rfc6749#section-5.1)\n */\nexport class TokenResponse implements TokenResponseConfig {\n /**\n * Determines whether a token refresh request must be made to refresh the tokens\n *\n * @param token\n * @param secondsMargin\n */\n static isTokenFresh(\n token: Pick<TokenResponse, 'expiresIn' | 'issuedAt'>,\n /**\n * -10 minutes in seconds\n */\n secondsMargin: number = 60 * 10 * -1\n ): boolean {\n if (!token) {\n return false;\n }\n if (token.expiresIn) {\n const now = getCurrentTimeInSeconds();\n return now < token.issuedAt + token.expiresIn + secondsMargin;\n }\n // if there is no expiration time but we have an access token, it is assumed to never expire\n return true;\n }\n /**\n * Creates a `TokenResponse` from query parameters returned from an `AuthRequest`.\n *\n * @param params\n */\n static fromQueryParams(params: Record<string, string>): TokenResponse {\n return new TokenResponse({\n accessToken: params.access_token,\n refreshToken: params.refresh_token,\n scope: params.scope,\n state: params.state,\n idToken: params.id_token,\n // @ts-ignore: Expected specific string\n tokenType: params.token_type,\n // @ts-ignore: Expected number\n expiresIn: params.expires_in,\n // @ts-ignore: Expected number\n issuedAt: params.issued_at,\n });\n }\n\n accessToken: string;\n tokenType: TokenType;\n expiresIn?: number;\n refreshToken?: string;\n scope?: string;\n state?: string;\n idToken?: string;\n issuedAt: number;\n\n constructor(response: TokenResponseConfig) {\n this.accessToken = response.accessToken;\n this.tokenType = response.tokenType ?? 'bearer';\n this.expiresIn = response.expiresIn;\n this.refreshToken = response.refreshToken;\n this.scope = response.scope;\n this.state = response.state;\n this.idToken = response.idToken;\n this.issuedAt = response.issuedAt ?? getCurrentTimeInSeconds();\n }\n\n private applyResponseConfig(response: TokenResponseConfig) {\n this.accessToken = response.accessToken ?? this.accessToken;\n this.tokenType = response.tokenType ?? this.tokenType ?? 'bearer';\n this.expiresIn = response.expiresIn ?? this.expiresIn;\n this.refreshToken = response.refreshToken ?? this.refreshToken;\n this.scope = response.scope ?? this.scope;\n this.state = response.state ?? this.state;\n this.idToken = response.idToken ?? this.idToken;\n this.issuedAt = response.issuedAt ?? this.issuedAt ?? getCurrentTimeInSeconds();\n }\n\n getRequestConfig(): TokenResponseConfig {\n return {\n accessToken: this.accessToken,\n idToken: this.idToken,\n refreshToken: this.refreshToken,\n scope: this.scope,\n state: this.state,\n tokenType: this.tokenType,\n issuedAt: this.issuedAt,\n expiresIn: this.expiresIn,\n };\n }\n\n async refreshAsync(\n config: Omit<TokenRequestConfig, 'grantType' | 'refreshToken'>,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n ): Promise<TokenResponse> {\n const request = new RefreshTokenRequest({\n ...config,\n refreshToken: this.refreshToken,\n });\n const response = await request.performAsync(discovery);\n // Custom: reuse the refresh token if one wasn't returned\n response.refreshToken = response.refreshToken ?? this.refreshToken;\n const json = response.getRequestConfig();\n this.applyResponseConfig(json);\n return this;\n }\n\n shouldRefresh(): boolean {\n // no refresh token available and token has expired\n return !(TokenResponse.isTokenFresh(this) || !this.refreshToken);\n }\n}\n\nclass Request<T, B> {\n constructor(protected request: T) {}\n\n async performAsync(discovery: ServiceConfig.DiscoveryDocument): Promise<B> {\n throw new Error('performAsync must be extended');\n }\n\n getRequestConfig(): T {\n throw new Error('getRequestConfig must be extended');\n }\n\n getQueryBody(): Record<string, string> {\n throw new Error('getQueryBody must be extended');\n }\n}\n\n/**\n * A generic token request.\n */\nclass TokenRequest<T extends TokenRequestConfig> extends Request<T, TokenResponse> {\n readonly clientId: string;\n readonly clientSecret?: string;\n readonly scopes?: string[];\n readonly extraParams?: Record<string, string>;\n\n constructor(request, public grantType: GrantType) {\n super(request);\n this.clientId = request.clientId;\n this.clientSecret = request.clientSecret;\n this.extraParams = request.extraParams;\n this.scopes = request.scopes;\n }\n\n getHeaders(): Headers {\n const headers: Headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n if (typeof this.clientSecret !== 'undefined') {\n // If client secret exists, it should be converted to base64\n // https://tools.ietf.org/html/rfc6749#section-2.3.1\n const encodedClientId = encodeURIComponent(this.clientId);\n const encodedClientSecret = encodeURIComponent(this.clientSecret);\n const credentials = `${encodedClientId}:${encodedClientSecret}`;\n const basicAuth = Base64.encodeNoWrap(credentials);\n headers.Authorization = `Basic ${basicAuth}`;\n }\n\n return headers;\n }\n\n async performAsync(discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>) {\n // redirect URI must not be nil\n invariant(\n discovery.tokenEndpoint,\n `Cannot invoke \\`performAsync()\\` without a valid tokenEndpoint`\n );\n const response = await requestAsync<ServerTokenResponseConfig | ResponseErrorConfig>(\n discovery.tokenEndpoint,\n {\n dataType: 'json',\n method: 'POST',\n headers: this.getHeaders(),\n body: this.getQueryBody(),\n }\n );\n\n if ('error' in response) {\n throw new TokenError(response);\n }\n\n return new TokenResponse({\n accessToken: response.access_token,\n tokenType: response.token_type,\n expiresIn: response.expires_in,\n refreshToken: response.refresh_token,\n scope: response.scope,\n idToken: response.id_token,\n issuedAt: response.issued_at,\n });\n }\n\n getQueryBody() {\n const queryBody: Record<string, string> = {\n grant_type: this.grantType,\n };\n\n if (!this.clientSecret) {\n // Only add the client ID if client secret is not present, otherwise pass the client id with the secret in the request body.\n queryBody.client_id = this.clientId;\n }\n\n if (this.scopes) {\n queryBody.scope = this.scopes.join(' ');\n }\n\n if (this.extraParams) {\n for (const extra in this.extraParams) {\n if (extra in this.extraParams && !(extra in queryBody)) {\n queryBody[extra] = this.extraParams[extra];\n }\n }\n }\n return queryBody;\n }\n}\n\n/**\n * Access token request. Exchange an authorization code for a user access token.\n *\n * [Section 4.1.3](https://tools.ietf.org/html/rfc6749#section-4.1.3)\n */\nexport class AccessTokenRequest\n extends TokenRequest<AccessTokenRequestConfig>\n implements AccessTokenRequestConfig\n{\n readonly code: string;\n readonly redirectUri: string;\n\n constructor(options: AccessTokenRequestConfig) {\n invariant(\n options.redirectUri,\n `\\`AccessTokenRequest\\` requires a valid \\`redirectUri\\` (it must also match the one used in the auth request). Example: ${Platform.select(\n {\n web: 'https://yourwebsite.com/redirect',\n default: 'myapp://redirect',\n }\n )}`\n );\n\n invariant(\n options.code,\n `\\`AccessTokenRequest\\` requires a valid authorization \\`code\\`. This is what's received from the authorization server after an auth request.`\n );\n super(options, GrantType.AuthorizationCode);\n this.code = options.code;\n this.redirectUri = options.redirectUri;\n }\n\n getQueryBody() {\n const queryBody: Record<string, string> = super.getQueryBody();\n\n if (this.redirectUri) {\n queryBody.redirect_uri = this.redirectUri;\n }\n\n if (this.code) {\n queryBody.code = this.code;\n }\n\n return queryBody;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n grantType: this.grantType,\n code: this.code,\n redirectUri: this.redirectUri,\n extraParams: this.extraParams,\n scopes: this.scopes,\n };\n }\n}\n\n/**\n * Refresh request.\n *\n * [Section 6](https://tools.ietf.org/html/rfc6749#section-6)\n */\nexport class RefreshTokenRequest\n extends TokenRequest<RefreshTokenRequestConfig>\n implements RefreshTokenRequestConfig\n{\n readonly refreshToken?: string;\n\n constructor(options: RefreshTokenRequestConfig) {\n invariant(options.refreshToken, `\\`RefreshTokenRequest\\` requires a valid \\`refreshToken\\`.`);\n super(options, GrantType.RefreshToken);\n this.refreshToken = options.refreshToken;\n }\n\n getQueryBody() {\n const queryBody = super.getQueryBody();\n\n if (this.refreshToken) {\n queryBody.refresh_token = this.refreshToken;\n }\n\n return queryBody;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n grantType: this.grantType,\n refreshToken: this.refreshToken,\n extraParams: this.extraParams,\n scopes: this.scopes,\n };\n }\n}\n\n/**\n * Revocation request for a given token.\n *\n * [Section 2.1](https://tools.ietf.org/html/rfc7009#section-2.1)\n */\nexport class RevokeTokenRequest\n extends Request<RevokeTokenRequestConfig, boolean>\n implements RevokeTokenRequestConfig\n{\n readonly clientId?: string;\n readonly clientSecret?: string;\n readonly token: string;\n readonly tokenTypeHint?: TokenTypeHint;\n\n constructor(request: RevokeTokenRequestConfig) {\n super(request);\n invariant(request.token, `\\`RevokeTokenRequest\\` requires a valid \\`token\\` to revoke.`);\n this.clientId = request.clientId;\n this.clientSecret = request.clientSecret;\n this.token = request.token;\n this.tokenTypeHint = request.tokenTypeHint;\n }\n\n getHeaders(): Headers {\n const headers: Headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n if (typeof this.clientSecret !== 'undefined' && this.clientId) {\n // If client secret exists, it should be converted to base64\n // https://tools.ietf.org/html/rfc6749#section-2.3.1\n const encodedClientId = encodeURIComponent(this.clientId);\n const encodedClientSecret = encodeURIComponent(this.clientSecret);\n const credentials = `${encodedClientId}:${encodedClientSecret}`;\n const basicAuth = Base64.encodeNoWrap(credentials);\n headers.Authorization = `Basic ${basicAuth}`;\n }\n\n return headers;\n }\n\n /**\n * Perform a token revocation request.\n *\n * @param discovery The `revocationEndpoint` for a provider.\n */\n async performAsync(discovery: Pick<ServiceConfig.DiscoveryDocument, 'revocationEndpoint'>) {\n invariant(\n discovery.revocationEndpoint,\n `Cannot invoke \\`performAsync()\\` without a valid revocationEndpoint`\n );\n await requestAsync<boolean>(discovery.revocationEndpoint, {\n method: 'POST',\n headers: this.getHeaders(),\n body: this.getQueryBody(),\n });\n\n return true;\n }\n\n getRequestConfig() {\n return {\n clientId: this.clientId,\n clientSecret: this.clientSecret,\n token: this.token,\n tokenTypeHint: this.tokenTypeHint,\n };\n }\n\n getQueryBody(): Record<string, string> {\n const queryBody: Record<string, string> = { token: this.token };\n if (this.tokenTypeHint) {\n queryBody.token_type_hint = this.tokenTypeHint;\n }\n // Include client creds https://tools.ietf.org/html/rfc6749#section-2.3.1\n if (this.clientId) {\n queryBody.client_id = this.clientId;\n }\n if (this.clientSecret) {\n queryBody.client_secret = this.clientSecret;\n }\n return queryBody;\n }\n}\n\n/**\n * Exchange an auth code for an access token that can be used to get data from the provider.\n *\n * @param config\n * @param discovery The `tokenEndpoint` for a provider.\n */\nexport function exchangeCodeAsync(\n config: AccessTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n): Promise<TokenResponse> {\n const request = new AccessTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Refresh an access token. Often this just requires the `refreshToken` and `scopes` parameters.\n *\n * [Section 6](https://tools.ietf.org/html/rfc6749#section-6)\n *\n * @param config\n * @param discovery The `tokenEndpoint` for a provider.\n */\nexport function refreshAsync(\n config: RefreshTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'tokenEndpoint'>\n): Promise<TokenResponse> {\n const request = new RefreshTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Revoke a token with a provider.\n * This makes the token unusable, effectively requiring the user to login again.\n *\n * @param config\n * @param discovery The `revocationEndpoint` for a provider.\n */\nexport function revokeAsync(\n config: RevokeTokenRequestConfig,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'revocationEndpoint'>\n): Promise<boolean> {\n const request = new RevokeTokenRequest(config);\n return request.performAsync(discovery);\n}\n\n/**\n * Fetch generic user info from the provider's OpenID Connect `userInfoEndpoint` (if supported).\n *\n * [UserInfo](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo)\n *\n * @param config The `accessToken` for a user, returned from a code exchange or auth request.\n * @param discovery The `userInfoEndpoint` for a provider.\n */\nexport function fetchUserInfoAsync(\n config: Pick<TokenResponse, 'accessToken'>,\n discovery: Pick<ServiceConfig.DiscoveryDocument, 'userInfoEndpoint'>\n): Promise<Record<string, any>> {\n if (!discovery.userInfoEndpoint) {\n throw new Error('User info endpoint is not defined in the service config discovery document');\n }\n return requestAsync<Record<string, any>>(discovery.userInfoEndpoint, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n Authorization: `Bearer ${config.accessToken}`,\n },\n dataType: 'json',\n method: 'GET',\n });\n}\n"]}
|
|
@@ -14,6 +14,7 @@ export const discovery = {
|
|
|
14
14
|
tokenEndpoint: 'https://graph.facebook.com/v6.0/oauth/access_token',
|
|
15
15
|
};
|
|
16
16
|
class FacebookAuthRequest extends AuthRequest {
|
|
17
|
+
nonce;
|
|
17
18
|
constructor({ language,
|
|
18
19
|
// Account selection cannot be reliably emulated on Facebook.
|
|
19
20
|
extraParams = {}, clientSecret, ...config }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Facebook.js","sourceRoot":"","sources":["../../src/providers/Facebook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EACL,WAAW,EAKX,eAAe,EACf,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEvE,MAAM,QAAQ,GAAG;IACf,cAAc,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IAC3C,kFAAkF;IAClF,aAAa,EAAE,CAAC,gBAAgB,EAAE,OAAO,CAAC;CAC3C,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAsB;IAC1C,qBAAqB,EAAE,4CAA4C;IACnE,aAAa,EAAE,oDAAoD;CACpE,CAAC;AASF,MAAM,mBAAoB,SAAQ,WAAW;
|
|
1
|
+
{"version":3,"file":"Facebook.js","sourceRoot":"","sources":["../../src/providers/Facebook.ts"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\nimport { Platform } from 'react-native';\n\nimport { AuthRequestConfig } from '../AuthRequest.types';\nimport { useAuthRequestResult, useLoadedAuthRequest } from '../AuthRequestHooks';\nimport {\n AuthRequest,\n AuthRequestPromptOptions,\n AuthSessionRedirectUriOptions,\n AuthSessionResult,\n DiscoveryDocument,\n makeRedirectUri,\n ResponseType,\n} from '../AuthSession';\nimport { generateHexStringAsync } from '../PKCE';\nimport { ProviderAuthRequestConfig } from './Provider.types';\nimport { applyRequiredScopes, useProxyEnabled } from './ProviderUtils';\n\nconst settings = {\n windowFeatures: { width: 700, height: 600 },\n // These are required for Firebase to work properly which is a reasonable default.\n minimumScopes: ['public_profile', 'email'],\n};\n\nexport const discovery: DiscoveryDocument = {\n authorizationEndpoint: 'https://www.facebook.com/v6.0/dialog/oauth',\n tokenEndpoint: 'https://graph.facebook.com/v6.0/oauth/access_token',\n};\n\nexport interface FacebookAuthRequestConfig extends ProviderAuthRequestConfig {\n webClientId?: string;\n iosClientId?: string;\n androidClientId?: string;\n expoClientId?: string;\n}\n\nclass FacebookAuthRequest extends AuthRequest {\n nonce?: string;\n\n constructor({\n language,\n // Account selection cannot be reliably emulated on Facebook.\n extraParams = {},\n clientSecret,\n ...config\n }: FacebookAuthRequestConfig) {\n const inputParams: Record<string, string> = {\n display: 'popup',\n ...extraParams,\n };\n if (language) {\n inputParams.locale = language;\n }\n\n // Apply the default scopes\n const scopes = applyRequiredScopes(config.scopes, settings.minimumScopes);\n let inputClientSecret: string | undefined;\n // Facebook will throw if you attempt to use the client secret\n if (config.responseType && config.responseType !== ResponseType.Code) {\n // TODO: maybe warn that you shouldn't store the client secret on the client\n inputClientSecret = clientSecret;\n }\n // Default to implicit auth\n if (!config.responseType) {\n config.responseType = ResponseType.Token;\n }\n super({\n ...config,\n clientSecret: inputClientSecret,\n scopes,\n extraParams: inputParams,\n });\n }\n\n /**\n * Load and return a valid auth request based on the input config.\n */\n async getAuthRequestConfigAsync(): Promise<AuthRequestConfig> {\n const { extraParams = {}, ...config } = await super.getAuthRequestConfigAsync();\n if (!extraParams.nonce && !this.nonce) {\n if (!this.nonce) {\n this.nonce = await generateHexStringAsync(16);\n }\n extraParams.auth_nonce = this.nonce;\n }\n return {\n ...config,\n extraParams,\n };\n }\n}\n\n/**\n * Load an authorization request.\n * Returns a loaded request, a response, and a prompt method.\n * When the prompt method completes then the response will be fulfilled.\n *\n * - [Get Started](https://docs.expo.io/guides/authentication/#facebook)\n *\n * @param config\n * @param discovery\n */\nexport function useAuthRequest(\n config: Partial<FacebookAuthRequestConfig> = {},\n redirectUriOptions: Partial<AuthSessionRedirectUriOptions> = {}\n): [\n FacebookAuthRequest | null,\n AuthSessionResult | null,\n (options?: AuthRequestPromptOptions) => Promise<AuthSessionResult>\n] {\n const useProxy = useProxyEnabled(redirectUriOptions);\n\n const clientId = useMemo((): string => {\n const propertyName = useProxy\n ? 'expoClientId'\n : Platform.select({\n ios: 'iosClientId',\n android: 'androidClientId',\n default: 'webClientId',\n });\n return config[propertyName as any] ?? config.clientId;\n }, [\n useProxy,\n config.expoClientId,\n config.iosClientId,\n config.androidClientId,\n config.webClientId,\n config.clientId,\n ]);\n\n const redirectUri = useMemo((): string => {\n if (typeof config.redirectUri !== 'undefined') {\n return config.redirectUri;\n }\n\n return makeRedirectUri({\n // The redirect URI should be created using fb + client ID on native.\n native: `fb${clientId}://authorize`,\n useProxy,\n ...redirectUriOptions,\n });\n }, [useProxy, clientId, config.redirectUri, redirectUriOptions]);\n\n const extraParams = useMemo((): FacebookAuthRequestConfig['extraParams'] => {\n const output = config.extraParams ? { ...config.extraParams } : {};\n\n if (config.language) {\n output.locale = config.language;\n }\n return output;\n }, [config.extraParams, config.language]);\n\n const request = useLoadedAuthRequest(\n {\n ...config,\n extraParams,\n clientId,\n redirectUri,\n },\n discovery,\n FacebookAuthRequest\n );\n\n const [result, promptAsync] = useAuthRequestResult(request, discovery, {\n windowFeatures: settings.windowFeatures,\n useProxy,\n });\n\n return [request, result, promptAsync];\n}\n"]}
|
|
@@ -20,6 +20,7 @@ export const discovery = {
|
|
|
20
20
|
userInfoEndpoint: 'https://openidconnect.googleapis.com/v1/userinfo',
|
|
21
21
|
};
|
|
22
22
|
class GoogleAuthRequest extends AuthRequest {
|
|
23
|
+
nonce;
|
|
23
24
|
constructor({ language, loginHint, selectAccount, extraParams = {}, clientSecret, ...config }) {
|
|
24
25
|
const inputParams = {
|
|
25
26
|
...extraParams,
|
|
@@ -148,6 +149,7 @@ export function useAuthRequest(config = {}, redirectUriOptions = {}) {
|
|
|
148
149
|
native: `${Application.applicationId}:/oauthredirect`,
|
|
149
150
|
useProxy,
|
|
150
151
|
...redirectUriOptions,
|
|
152
|
+
// native: `com.googleusercontent.apps.${guid}:/oauthredirect`,
|
|
151
153
|
});
|
|
152
154
|
}, [useProxy, config.redirectUri, redirectUriOptions]);
|
|
153
155
|
const extraParams = useMemo(() => {
|
|
@@ -186,7 +188,7 @@ export function useAuthRequest(config = {}, redirectUriOptions = {}) {
|
|
|
186
188
|
}, [config.shouldAutoExchangeCode, result?.type]);
|
|
187
189
|
useEffect(() => {
|
|
188
190
|
let isMounted = true;
|
|
189
|
-
if (
|
|
191
|
+
if (shouldAutoExchangeCode && result?.type === 'success') {
|
|
190
192
|
const exchangeRequest = new AccessTokenRequest({
|
|
191
193
|
clientId,
|
|
192
194
|
clientSecret: config.clientSecret,
|
|
@@ -198,7 +200,7 @@ export function useAuthRequest(config = {}, redirectUriOptions = {}) {
|
|
|
198
200
|
code_verifier: request.codeVerifier,
|
|
199
201
|
},
|
|
200
202
|
});
|
|
201
|
-
exchangeRequest.performAsync(discovery).then(authentication => {
|
|
203
|
+
exchangeRequest.performAsync(discovery).then((authentication) => {
|
|
202
204
|
if (isMounted) {
|
|
203
205
|
setFullResult({
|
|
204
206
|
...result,
|
|
@@ -214,7 +216,7 @@ export function useAuthRequest(config = {}, redirectUriOptions = {}) {
|
|
|
214
216
|
});
|
|
215
217
|
}
|
|
216
218
|
else {
|
|
217
|
-
setFullResult(
|
|
219
|
+
setFullResult(result);
|
|
218
220
|
}
|
|
219
221
|
return () => {
|
|
220
222
|
isMounted = false;
|
|
@@ -226,7 +228,7 @@ export function useAuthRequest(config = {}, redirectUriOptions = {}) {
|
|
|
226
228
|
config.clientSecret,
|
|
227
229
|
config.scopes?.join(','),
|
|
228
230
|
request?.codeVerifier,
|
|
229
|
-
|
|
231
|
+
result,
|
|
230
232
|
]);
|
|
231
233
|
return [request, fullResult, promptAsync];
|
|
232
234
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Google.js","sourceRoot":"","sources":["../../src/providers/Google.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EACL,WAAW,EAMX,sBAAsB,EACtB,eAAe,EACf,MAAM,EACN,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAE1F,MAAM,QAAQ,GAAG;IACf,cAAc,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IAC3C,aAAa,EAAE;QACb,QAAQ;QACR,kDAAkD;QAClD,gDAAgD;KACjD;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAsB;IAC1C,qBAAqB,EAAE,8CAA8C;IACrE,aAAa,EAAE,qCAAqC;IACpD,kBAAkB,EAAE,sCAAsC;IAC1D,gBAAgB,EAAE,kDAAkD;CACrE,CAAC;AA+EF,MAAM,iBAAkB,SAAQ,WAAW;IAGzC,YAAY,EACV,QAAQ,EACR,SAAS,EACT,aAAa,EACb,WAAW,GAAG,EAAE,EAChB,YAAY,EACZ,GAAG,MAAM,EACe;QACxB,MAAM,WAAW,GAAG;YAClB,GAAG,WAAW;SACf,CAAC;QACF,IAAI,QAAQ;YAAE,WAAW,CAAC,EAAE,GAAG,QAAQ,CAAC;QACxC,IAAI,SAAS;YAAE,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC;QAClD,IAAI,aAAa;YAAE,WAAW,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;QAE7D,2BAA2B;QAC3B,MAAM,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC1E,MAAM,UAAU,GACd,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,KAAK,IAAI,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,OAAO,CAAC;QAC7F,IAAI,UAAU,EAAE;YACd,0CAA0C;YAC1C,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;SACxB;QACD,IAAI,iBAAqC,CAAC;QAC1C,6DAA6D;QAC7D,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,IAAI,EAAE;YACpE,4EAA4E;YAC5E,iBAAiB,GAAG,YAAY,CAAC;SAClC;QACD,KAAK,CAAC;YACJ,GAAG,MAAM;YACT,YAAY,EAAE,iBAAiB;YAC/B,MAAM;YACN,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,yBAAyB;QAC7B,MAAM,EAAE,WAAW,GAAG,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,yBAAyB,EAAE,CAAC;QAChF,IAAI,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,OAAO,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;YACrF,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE;gBACf,IAAI,CAAC,KAAK,GAAG,MAAM,sBAAsB,CAAC,EAAE,CAAC,CAAC;aAC/C;YACD,WAAW,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;SAChC;QACD,OAAO;YACL,GAAG,MAAM;YACT,WAAW;SACZ,CAAC;IACJ,CAAC;CACF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAwC,EACxC,qBAA6D,EAAE;IAM/D,MAAM,QAAQ,GAAG,eAAe,CAAC,kBAAkB,CAAC,CAAC;IAErD,MAAM,SAAS,GAAG,QAAQ,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,CAAC;IAEpD,OAAO,cAAc,CACnB;QACE,GAAG,MAAM;QACT,YAAY;QACV,yDAAyD;QACzD,CAAC,MAAM,CAAC,YAAY;YACpB,2FAA2F;YAC3F,SAAS;YACP,CAAC,CAAC,YAAY,CAAC,OAAO;YACtB,CAAC,CAAC,SAAS;KAChB,EACD,EAAE,GAAG,kBAAkB,EAAE,QAAQ,EAAE,CACpC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,SAA2C,EAAE,EAC7C,qBAA6D,EAAE;IAM/D,MAAM,QAAQ,GAAG,eAAe,CAAC,kBAAkB,CAAC,CAAC;IAErD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAW,EAAE;QACpC,MAAM,YAAY,GAAG,QAAQ;YAC3B,CAAC,CAAC,cAAc;YAChB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACd,GAAG,EAAE,aAAa;gBAClB,OAAO,EAAE,iBAAiB;gBAC1B,OAAO,EAAE,aAAa;aACvB,CAAC,CAAC;QAEP,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAmB,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC;QAChE,iBAAiB,CAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,QAAQ,CAAC;IAClB,CAAC,EAAE;QACD,QAAQ;QACR,MAAM,CAAC,YAAY;QACnB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,eAAe;QACtB,MAAM,CAAC,WAAW;QAClB,MAAM,CAAC,QAAQ;KAChB,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,EAAE;QAChC,mBAAmB;QACnB,IAAI,OAAO,MAAM,CAAC,YAAY,KAAK,WAAW,EAAE;YAC9C,OAAO,MAAM,CAAC,YAAY,CAAC;SAC5B;QACD,yFAAyF;QACzF,sGAAsG;QACtG,MAAM,cAAc,GAAG,QAAQ,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,QAAQ,CAAC;QAC1D,8FAA8F;QAC9F,IAAI,MAAM,CAAC,YAAY,IAAI,cAAc,EAAE;YACzC,OAAO,YAAY,CAAC,IAAI,CAAC;SAC1B;QACD,4HAA4H;QAC5H,OAAO,YAAY,CAAC,KAAK,CAAC;IAC5B,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAW,EAAE;QACvC,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,WAAW,EAAE;YAC7C,OAAO,MAAM,CAAC,WAAW,CAAC;SAC3B;QAED,OAAO,eAAe,CAAC;YACrB,MAAM,EAAE,GAAG,WAAW,CAAC,aAAa,iBAAiB;YACrD,QAAQ;YACR,GAAG,kBAAkB;SAEtB,CAAC,CAAC;IACL,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,OAAO,CAAC,GAA2C,EAAE;QACvE,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnE,IAAI,MAAM,CAAC,QAAQ,EAAE;YACnB,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;SAC7B;QACD,IAAI,MAAM,CAAC,SAAS,EAAE;YACpB,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC;SACtC;QACD,IAAI,MAAM,CAAC,aAAa,EAAE;YACxB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,CAAC;SACtC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;IAElF,MAAM,OAAO,GAAG,oBAAoB,CAClC;QACE,GAAG,MAAM;QACT,YAAY;QACZ,WAAW;QACX,QAAQ;QACR,WAAW;KACZ,EACD,SAAS,EACT,iBAAiB,CAClB,CAAC;IAEF,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,oBAAoB,CAAC,OAAO,EAAE,SAAS,EAAE;QACrE,QAAQ;QACR,cAAc,EAAE,QAAQ,CAAC,cAAc;KACxC,CAAC,CAAC;IAEH,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAA2B,IAAI,CAAC,CAAC;IAE7E,MAAM,sBAAsB,GAAG,OAAO,CAAC,GAAG,EAAE;QAC1C,kBAAkB;QAClB,IAAI,OAAO,MAAM,CAAC,sBAAsB,KAAK,WAAW,EAAE;YACxD,OAAO,MAAM,CAAC,sBAAsB,CAAC;SACtC;QAED,iEAAiE;QACjE,MAAM,iBAAiB,GACrB,MAAM,EAAE,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC;QAE7E,OAAO,iBAAiB,CAAC;IAC3B,CAAC,EAAE,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;IAElD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,SAAS,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,UAAU,IAAI,sBAAsB,IAAI,MAAM,EAAE,IAAI,KAAK,SAAS,EAAE;YACvE,MAAM,eAAe,GAAG,IAAI,kBAAkB,CAAC;gBAC7C,QAAQ;gBACR,YAAY,EAAE,MAAM,CAAC,YAAY;gBACjC,WAAW;gBACX,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;gBACxB,WAAW,EAAE;oBACX,yDAAyD;oBACzD,aAAa,EAAE,OAAO,CAAC,YAAY;iBACpC;aACF,CAAC,CAAC;YACH,eAAe,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE;gBAC5D,IAAI,SAAS,EAAE;oBACb,aAAa,CAAC;wBACZ,GAAG,MAAM;wBACT,MAAM,EAAE;4BACN,0GAA0G;4BAC1G,QAAQ,EAAE,cAAc,CAAC,OAAO;4BAChC,YAAY,EAAE,cAAc,CAAC,WAAW;4BACxC,GAAG,MAAM,CAAC,MAAM;yBACjB;wBACD,cAAc;qBACf,CAAC,CAAC;iBACJ;YACH,CAAC,CAAC,CAAC;SACJ;aAAM;YACL,aAAa,CAAC,UAAU,IAAI,MAAM,CAAC,CAAC;SACrC;QACD,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,QAAQ;QACR,WAAW;QACX,sBAAsB;QACtB,MAAM,CAAC,YAAY;QACnB,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC;QACxB,OAAO,EAAE,YAAY;QACrB,UAAU;KACX,CAAC,CAAC;IAEH,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import * as Application from 'expo-application';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Platform } from 'react-native';\n\nimport { useAuthRequestResult, useLoadedAuthRequest } from '../AuthRequestHooks';\nimport {\n AuthRequest,\n AuthRequestConfig,\n AuthRequestPromptOptions,\n AuthSessionRedirectUriOptions,\n AuthSessionResult,\n DiscoveryDocument,\n generateHexStringAsync,\n makeRedirectUri,\n Prompt,\n ResponseType,\n} from '../AuthSession';\nimport { AccessTokenRequest } from '../TokenRequest';\nimport { ProviderAuthRequestConfig } from './Provider.types';\nimport { applyRequiredScopes, invariantClientId, useProxyEnabled } from './ProviderUtils';\n\nconst settings = {\n windowFeatures: { width: 515, height: 680 },\n minimumScopes: [\n 'openid',\n 'https://www.googleapis.com/auth/userinfo.profile',\n 'https://www.googleapis.com/auth/userinfo.email',\n ],\n};\n\nexport const discovery: DiscoveryDocument = {\n authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenEndpoint: 'https://oauth2.googleapis.com/token',\n revocationEndpoint: 'https://oauth2.googleapis.com/revoke',\n userInfoEndpoint: 'https://openidconnect.googleapis.com/v1/userinfo',\n};\n\nexport interface GoogleAuthRequestConfig extends ProviderAuthRequestConfig {\n /**\n * If the user's email address is known ahead of time, it can be supplied to be the default option.\n * If the user has approved access for this app in the past then auth may return without any further interaction.\n */\n loginHint?: string;\n /**\n * When `true`, the service will allow the user to switch between accounts (if possible). Defaults to `false`.\n */\n selectAccount?: boolean;\n /**\n * Proxy client ID for use in the Expo client on iOS and Android.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Web Application\n * - **URIs**: https://auth.expo.io\n * - **Authorized redirect URIs**: https://auth.expo.io/@your-username/your-project-slug\n */\n expoClientId?: string;\n /**\n * Expo web client ID for use in the browser.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Web Application\n * - Give it a name (e.g. \"Web App\").\n * - **URIs** (Authorized JavaScript origins): https://localhost:19006 & https://yourwebsite.com\n * - **Authorized redirect URIs**: https://localhost:19006 & https://yourwebsite.com\n * - To test this be sure to start your app with `expo start:web --https`.\n */\n webClientId?: string;\n /**\n * iOS native client ID for use in standalone, bare workflow, and custom clients.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: iOS Application\n * - Give it a name (e.g. \"iOS App\").\n * - **Bundle ID**: Must match the value of `ios.bundleIdentifier` in your `app.json`.\n * - Your app needs to conform to the URI scheme matching your bundle identifier.\n * - _Standalone_: Automatically added, do nothing.\n * - _Bare workflow_: Run `npx uri-scheme add <your bundle id> --ios`\n * - To test this you can:\n * 1. Eject to bare: `expo eject` and run `yarn ios`\n * 2. Create a custom client: `expo client:ios`\n * 3. Build a production IPA: `expo build:ios`\n * - Whenever you change the values in `app.json` you'll need to rebuild the native app.\n */\n iosClientId?: string;\n /**\n * Android native client ID for use in standalone, and bare workflow.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Android Application\n * - Give it a name (e.g. \"Android App\").\n * - **Package name**: Must match the value of `android.package` in your `app.json`.\n * - Your app needs to conform to the URI scheme matching your `android.package` (ex. `com.myname.mycoolapp:/`).\n * - _Standalone_: Automatically added, do nothing.\n * - _Bare workflow_: Run `npx uri-scheme add <your android.package> --android`\n * - **Signing-certificate fingerprint**:\n * - Run `expo credentials:manager -p android` then select \"Update upload Keystore\" -> \"Generate new keystore\" -> \"Go back to experience overview\"\n * - Copy your \"Google Certificate Fingerprint\", it will output a string that looks like `A1:B2:C3` but longer.\n * - To test this you can:\n * 1. Eject to bare: `expo eject` and run `yarn ios`\n * 2. Build a production IPA: `expo build:android`\n */\n androidClientId?: string;\n /**\n * Should the hook automatically exchange the response code for an authentication token.\n *\n * Defaults to true on installed apps (iOS, Android) when `ResponseType.Code` is used (default).\n */\n shouldAutoExchangeCode?: boolean;\n}\n\nclass GoogleAuthRequest extends AuthRequest {\n nonce?: string;\n\n constructor({\n language,\n loginHint,\n selectAccount,\n extraParams = {},\n clientSecret,\n ...config\n }: GoogleAuthRequestConfig) {\n const inputParams = {\n ...extraParams,\n };\n if (language) inputParams.hl = language;\n if (loginHint) inputParams.login_hint = loginHint;\n if (selectAccount) inputParams.prompt = Prompt.SelectAccount;\n\n // Apply the default scopes\n const scopes = applyRequiredScopes(config.scopes, settings.minimumScopes);\n const isImplicit =\n config.responseType === ResponseType.Token || config.responseType === ResponseType.IdToken;\n if (isImplicit) {\n // PKCE must be disabled in implicit mode.\n config.usePKCE = false;\n }\n let inputClientSecret: string | undefined;\n // Google will throw if you attempt to use the client secret\n if (config.responseType && config.responseType !== ResponseType.Code) {\n // TODO: maybe warn that you shouldn't store the client secret on the client\n inputClientSecret = clientSecret;\n }\n super({\n ...config,\n clientSecret: inputClientSecret,\n scopes,\n extraParams: inputParams,\n });\n }\n\n /**\n * Load and return a valid auth request based on the input config.\n */\n async getAuthRequestConfigAsync(): Promise<AuthRequestConfig> {\n const { extraParams = {}, ...config } = await super.getAuthRequestConfigAsync();\n if (config.responseType === ResponseType.IdToken && !extraParams.nonce && !this.nonce) {\n if (!this.nonce) {\n this.nonce = await generateHexStringAsync(16);\n }\n extraParams.nonce = this.nonce;\n }\n return {\n ...config,\n extraParams,\n };\n }\n}\n\n/**\n * Load an authorization request with an ID Token for authentication with Firebase.\n *\n * Returns a loaded request, a response, and a prompt method.\n * When the prompt method completes then the response will be fulfilled.\n *\n * The id token can be retrieved with `response.params.id_token`.\n *\n * - [Get Started](https://docs.expo.io/guides/authentication/#google)\n *\n * @param config\n * @param redirectUriOptions\n */\nexport function useIdTokenAuthRequest(\n config: Partial<GoogleAuthRequestConfig>,\n redirectUriOptions: Partial<AuthSessionRedirectUriOptions> = {}\n): [\n GoogleAuthRequest | null,\n AuthSessionResult | null,\n (options?: AuthRequestPromptOptions) => Promise<AuthSessionResult>\n] {\n const useProxy = useProxyEnabled(redirectUriOptions);\n\n const isWebAuth = useProxy || Platform.OS === 'web';\n\n return useAuthRequest(\n {\n ...config,\n responseType:\n // If the client secret is provided then code can be used\n !config.clientSecret &&\n // When web auth is used, we can request the `id_token` directly without exchanging a code.\n isWebAuth\n ? ResponseType.IdToken\n : undefined,\n },\n { ...redirectUriOptions, useProxy }\n );\n}\n\n/**\n * Load an authorization request.\n * Returns a loaded request, a response, and a prompt method.\n * When the prompt method completes, then the response will be fulfilled.\n *\n * - [Get Started](https://docs.expo.io/guides/authentication/#google)\n *\n * @param config\n * @param redirectUriOptions\n */\nexport function useAuthRequest(\n config: Partial<GoogleAuthRequestConfig> = {},\n redirectUriOptions: Partial<AuthSessionRedirectUriOptions> = {}\n): [\n GoogleAuthRequest | null,\n AuthSessionResult | null,\n (options?: AuthRequestPromptOptions) => Promise<AuthSessionResult>\n] {\n const useProxy = useProxyEnabled(redirectUriOptions);\n\n const clientId = useMemo((): string => {\n const propertyName = useProxy\n ? 'expoClientId'\n : Platform.select({\n ios: 'iosClientId',\n android: 'androidClientId',\n default: 'webClientId',\n });\n\n const clientId = config[propertyName as any] ?? config.clientId;\n invariantClientId(propertyName, clientId, 'Google');\n return clientId;\n }, [\n useProxy,\n config.expoClientId,\n config.iosClientId,\n config.androidClientId,\n config.webClientId,\n config.clientId,\n ]);\n\n const responseType = useMemo(() => {\n // Allow overrides.\n if (typeof config.responseType !== 'undefined') {\n return config.responseType;\n }\n // You can only use `response_token=code` on installed apps (iOS, Android without proxy).\n // Installed apps can auto exchange without a client secret and get the token and id-token (Firebase).\n const isInstalledApp = Platform.OS !== 'web' && !useProxy;\n // If the user provided the client secret (they shouldn't!) then use code exchange by default.\n if (config.clientSecret || isInstalledApp) {\n return ResponseType.Code;\n }\n // This seems the most pragmatic option since it can result in a full authentication on web and proxy platforms as expected.\n return ResponseType.Token;\n }, [config.responseType, config.clientSecret, useProxy]);\n\n const redirectUri = useMemo((): string => {\n if (typeof config.redirectUri !== 'undefined') {\n return config.redirectUri;\n }\n\n return makeRedirectUri({\n native: `${Application.applicationId}:/oauthredirect`,\n useProxy,\n ...redirectUriOptions,\n // native: `com.googleusercontent.apps.${guid}:/oauthredirect`,\n });\n }, [useProxy, config.redirectUri, redirectUriOptions]);\n\n const extraParams = useMemo((): GoogleAuthRequestConfig['extraParams'] => {\n const output = config.extraParams ? { ...config.extraParams } : {};\n\n if (config.language) {\n output.hl = output.language;\n }\n if (config.loginHint) {\n output.login_hint = output.loginHint;\n }\n if (config.selectAccount) {\n output.prompt = Prompt.SelectAccount;\n }\n return output;\n }, [config.extraParams, config.language, config.loginHint, config.selectAccount]);\n\n const request = useLoadedAuthRequest(\n {\n ...config,\n responseType,\n extraParams,\n clientId,\n redirectUri,\n },\n discovery,\n GoogleAuthRequest\n );\n\n const [result, promptAsync] = useAuthRequestResult(request, discovery, {\n useProxy,\n windowFeatures: settings.windowFeatures,\n });\n\n const [fullResult, setFullResult] = useState<AuthSessionResult | null>(null);\n\n const shouldAutoExchangeCode = useMemo(() => {\n // allow overrides\n if (typeof config.shouldAutoExchangeCode !== 'undefined') {\n return config.shouldAutoExchangeCode;\n }\n\n // has a code to exchange and doesn't have an authentication yet.\n const couldAutoExchange =\n result?.type === 'success' && result.params.code && !result.authentication;\n\n return couldAutoExchange;\n }, [config.shouldAutoExchangeCode, result?.type]);\n\n useEffect(() => {\n let isMounted = true;\n if (!fullResult && shouldAutoExchangeCode && result?.type === 'success') {\n const exchangeRequest = new AccessTokenRequest({\n clientId,\n clientSecret: config.clientSecret,\n redirectUri,\n scopes: config.scopes,\n code: result.params.code,\n extraParams: {\n // @ts-ignore: allow for instances where PKCE is disabled\n code_verifier: request.codeVerifier,\n },\n });\n exchangeRequest.performAsync(discovery).then(authentication => {\n if (isMounted) {\n setFullResult({\n ...result,\n params: {\n // @ts-ignore: provide a singular interface for getting the id_token across all workflows that request it.\n id_token: authentication.idToken,\n access_token: authentication.accessToken,\n ...result.params,\n },\n authentication,\n });\n }\n });\n } else {\n setFullResult(fullResult ?? result);\n }\n return () => {\n isMounted = false;\n };\n }, [\n clientId,\n redirectUri,\n shouldAutoExchangeCode,\n config.clientSecret,\n config.scopes?.join(','),\n request?.codeVerifier,\n fullResult,\n ]);\n\n return [request, fullResult, promptAsync];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Google.js","sourceRoot":"","sources":["../../src/providers/Google.ts"],"names":[],"mappings":"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","sourcesContent":["import * as Application from 'expo-application';\nimport { useEffect, useMemo, useState } from 'react';\nimport { Platform } from 'react-native';\n\nimport { useAuthRequestResult, useLoadedAuthRequest } from '../AuthRequestHooks';\nimport {\n AuthRequest,\n AuthRequestConfig,\n AuthRequestPromptOptions,\n AuthSessionRedirectUriOptions,\n AuthSessionResult,\n DiscoveryDocument,\n generateHexStringAsync,\n makeRedirectUri,\n Prompt,\n ResponseType,\n} from '../AuthSession';\nimport { AccessTokenRequest } from '../TokenRequest';\nimport { ProviderAuthRequestConfig } from './Provider.types';\nimport { applyRequiredScopes, invariantClientId, useProxyEnabled } from './ProviderUtils';\n\nconst settings = {\n windowFeatures: { width: 515, height: 680 },\n minimumScopes: [\n 'openid',\n 'https://www.googleapis.com/auth/userinfo.profile',\n 'https://www.googleapis.com/auth/userinfo.email',\n ],\n};\n\nexport const discovery: DiscoveryDocument = {\n authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',\n tokenEndpoint: 'https://oauth2.googleapis.com/token',\n revocationEndpoint: 'https://oauth2.googleapis.com/revoke',\n userInfoEndpoint: 'https://openidconnect.googleapis.com/v1/userinfo',\n};\n\nexport interface GoogleAuthRequestConfig extends ProviderAuthRequestConfig {\n /**\n * If the user's email address is known ahead of time, it can be supplied to be the default option.\n * If the user has approved access for this app in the past then auth may return without any further interaction.\n */\n loginHint?: string;\n /**\n * When `true`, the service will allow the user to switch between accounts (if possible). Defaults to `false`.\n */\n selectAccount?: boolean;\n /**\n * Proxy client ID for use in the Expo client on iOS and Android.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Web Application\n * - **URIs**: https://auth.expo.io\n * - **Authorized redirect URIs**: https://auth.expo.io/@your-username/your-project-slug\n */\n expoClientId?: string;\n /**\n * Expo web client ID for use in the browser.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Web Application\n * - Give it a name (e.g. \"Web App\").\n * - **URIs** (Authorized JavaScript origins): https://localhost:19006 & https://yourwebsite.com\n * - **Authorized redirect URIs**: https://localhost:19006 & https://yourwebsite.com\n * - To test this be sure to start your app with `expo start:web --https`.\n */\n webClientId?: string;\n /**\n * iOS native client ID for use in standalone, bare workflow, and custom clients.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: iOS Application\n * - Give it a name (e.g. \"iOS App\").\n * - **Bundle ID**: Must match the value of `ios.bundleIdentifier` in your `app.json`.\n * - Your app needs to conform to the URI scheme matching your bundle identifier.\n * - _Standalone_: Automatically added, do nothing.\n * - _Bare workflow_: Run `npx uri-scheme add <your bundle id> --ios`\n * - To test this you can:\n * 1. Eject to bare: `expo eject` and run `yarn ios`\n * 2. Create a custom client: `expo client:ios`\n * 3. Build a production IPA: `expo build:ios`\n * - Whenever you change the values in `app.json` you'll need to rebuild the native app.\n */\n iosClientId?: string;\n /**\n * Android native client ID for use in standalone, and bare workflow.\n *\n * This Google Client ID must be setup as follows:\n *\n * - **Application Type**: Android Application\n * - Give it a name (e.g. \"Android App\").\n * - **Package name**: Must match the value of `android.package` in your `app.json`.\n * - Your app needs to conform to the URI scheme matching your `android.package` (ex. `com.myname.mycoolapp:/`).\n * - _Standalone_: Automatically added, do nothing.\n * - _Bare workflow_: Run `npx uri-scheme add <your android.package> --android`\n * - **Signing-certificate fingerprint**:\n * - Run `expo credentials:manager -p android` then select \"Update upload Keystore\" -> \"Generate new keystore\" -> \"Go back to experience overview\"\n * - Copy your \"Google Certificate Fingerprint\", it will output a string that looks like `A1:B2:C3` but longer.\n * - To test this you can:\n * 1. Eject to bare: `expo eject` and run `yarn ios`\n * 2. Build a production IPA: `expo build:android`\n */\n androidClientId?: string;\n /**\n * Should the hook automatically exchange the response code for an authentication token.\n *\n * Defaults to true on installed apps (iOS, Android) when `ResponseType.Code` is used (default).\n */\n shouldAutoExchangeCode?: boolean;\n}\n\nclass GoogleAuthRequest extends AuthRequest {\n nonce?: string;\n\n constructor({\n language,\n loginHint,\n selectAccount,\n extraParams = {},\n clientSecret,\n ...config\n }: GoogleAuthRequestConfig) {\n const inputParams = {\n ...extraParams,\n };\n if (language) inputParams.hl = language;\n if (loginHint) inputParams.login_hint = loginHint;\n if (selectAccount) inputParams.prompt = Prompt.SelectAccount;\n\n // Apply the default scopes\n const scopes = applyRequiredScopes(config.scopes, settings.minimumScopes);\n const isImplicit =\n config.responseType === ResponseType.Token || config.responseType === ResponseType.IdToken;\n if (isImplicit) {\n // PKCE must be disabled in implicit mode.\n config.usePKCE = false;\n }\n let inputClientSecret: string | undefined;\n // Google will throw if you attempt to use the client secret\n if (config.responseType && config.responseType !== ResponseType.Code) {\n // TODO: maybe warn that you shouldn't store the client secret on the client\n inputClientSecret = clientSecret;\n }\n super({\n ...config,\n clientSecret: inputClientSecret,\n scopes,\n extraParams: inputParams,\n });\n }\n\n /**\n * Load and return a valid auth request based on the input config.\n */\n async getAuthRequestConfigAsync(): Promise<AuthRequestConfig> {\n const { extraParams = {}, ...config } = await super.getAuthRequestConfigAsync();\n if (config.responseType === ResponseType.IdToken && !extraParams.nonce && !this.nonce) {\n if (!this.nonce) {\n this.nonce = await generateHexStringAsync(16);\n }\n extraParams.nonce = this.nonce;\n }\n return {\n ...config,\n extraParams,\n };\n }\n}\n\n/**\n * Load an authorization request with an ID Token for authentication with Firebase.\n *\n * Returns a loaded request, a response, and a prompt method.\n * When the prompt method completes then the response will be fulfilled.\n *\n * The id token can be retrieved with `response.params.id_token`.\n *\n * - [Get Started](https://docs.expo.io/guides/authentication/#google)\n *\n * @param config\n * @param redirectUriOptions\n */\nexport function useIdTokenAuthRequest(\n config: Partial<GoogleAuthRequestConfig>,\n redirectUriOptions: Partial<AuthSessionRedirectUriOptions> = {}\n): [\n GoogleAuthRequest | null,\n AuthSessionResult | null,\n (options?: AuthRequestPromptOptions) => Promise<AuthSessionResult>\n] {\n const useProxy = useProxyEnabled(redirectUriOptions);\n\n const isWebAuth = useProxy || Platform.OS === 'web';\n\n return useAuthRequest(\n {\n ...config,\n responseType:\n // If the client secret is provided then code can be used\n !config.clientSecret &&\n // When web auth is used, we can request the `id_token` directly without exchanging a code.\n isWebAuth\n ? ResponseType.IdToken\n : undefined,\n },\n { ...redirectUriOptions, useProxy }\n );\n}\n\n/**\n * Load an authorization request.\n * Returns a loaded request, a response, and a prompt method.\n * When the prompt method completes, then the response will be fulfilled.\n *\n * - [Get Started](https://docs.expo.io/guides/authentication/#google)\n *\n * @param config\n * @param redirectUriOptions\n */\nexport function useAuthRequest(\n config: Partial<GoogleAuthRequestConfig> = {},\n redirectUriOptions: Partial<AuthSessionRedirectUriOptions> = {}\n): [\n GoogleAuthRequest | null,\n AuthSessionResult | null,\n (options?: AuthRequestPromptOptions) => Promise<AuthSessionResult>\n] {\n const useProxy = useProxyEnabled(redirectUriOptions);\n\n const clientId = useMemo((): string => {\n const propertyName = useProxy\n ? 'expoClientId'\n : Platform.select({\n ios: 'iosClientId',\n android: 'androidClientId',\n default: 'webClientId',\n });\n\n const clientId = config[propertyName as any] ?? config.clientId;\n invariantClientId(propertyName, clientId, 'Google');\n return clientId;\n }, [\n useProxy,\n config.expoClientId,\n config.iosClientId,\n config.androidClientId,\n config.webClientId,\n config.clientId,\n ]);\n\n const responseType = useMemo(() => {\n // Allow overrides.\n if (typeof config.responseType !== 'undefined') {\n return config.responseType;\n }\n // You can only use `response_token=code` on installed apps (iOS, Android without proxy).\n // Installed apps can auto exchange without a client secret and get the token and id-token (Firebase).\n const isInstalledApp = Platform.OS !== 'web' && !useProxy;\n // If the user provided the client secret (they shouldn't!) then use code exchange by default.\n if (config.clientSecret || isInstalledApp) {\n return ResponseType.Code;\n }\n // This seems the most pragmatic option since it can result in a full authentication on web and proxy platforms as expected.\n return ResponseType.Token;\n }, [config.responseType, config.clientSecret, useProxy]);\n\n const redirectUri = useMemo((): string => {\n if (typeof config.redirectUri !== 'undefined') {\n return config.redirectUri;\n }\n\n return makeRedirectUri({\n native: `${Application.applicationId}:/oauthredirect`,\n useProxy,\n ...redirectUriOptions,\n // native: `com.googleusercontent.apps.${guid}:/oauthredirect`,\n });\n }, [useProxy, config.redirectUri, redirectUriOptions]);\n\n const extraParams = useMemo((): GoogleAuthRequestConfig['extraParams'] => {\n const output = config.extraParams ? { ...config.extraParams } : {};\n\n if (config.language) {\n output.hl = output.language;\n }\n if (config.loginHint) {\n output.login_hint = output.loginHint;\n }\n if (config.selectAccount) {\n output.prompt = Prompt.SelectAccount;\n }\n return output;\n }, [config.extraParams, config.language, config.loginHint, config.selectAccount]);\n\n const request = useLoadedAuthRequest(\n {\n ...config,\n responseType,\n extraParams,\n clientId,\n redirectUri,\n },\n discovery,\n GoogleAuthRequest\n );\n\n const [result, promptAsync] = useAuthRequestResult(request, discovery, {\n useProxy,\n windowFeatures: settings.windowFeatures,\n });\n\n const [fullResult, setFullResult] = useState<AuthSessionResult | null>(null);\n\n const shouldAutoExchangeCode = useMemo(() => {\n // allow overrides\n if (typeof config.shouldAutoExchangeCode !== 'undefined') {\n return config.shouldAutoExchangeCode;\n }\n\n // has a code to exchange and doesn't have an authentication yet.\n const couldAutoExchange =\n result?.type === 'success' && result.params.code && !result.authentication;\n\n return couldAutoExchange;\n }, [config.shouldAutoExchangeCode, result?.type]);\n\n useEffect(() => {\n let isMounted = true;\n if (shouldAutoExchangeCode && result?.type === 'success') {\n const exchangeRequest = new AccessTokenRequest({\n clientId,\n clientSecret: config.clientSecret,\n redirectUri,\n scopes: config.scopes,\n code: result.params.code,\n extraParams: {\n // @ts-ignore: allow for instances where PKCE is disabled\n code_verifier: request.codeVerifier,\n },\n });\n exchangeRequest.performAsync(discovery).then((authentication) => {\n if (isMounted) {\n setFullResult({\n ...result,\n params: {\n // @ts-ignore: provide a singular interface for getting the id_token across all workflows that request it.\n id_token: authentication.idToken,\n access_token: authentication.accessToken,\n ...result.params,\n },\n authentication,\n });\n }\n });\n } else {\n setFullResult(result);\n }\n return () => {\n isMounted = false;\n };\n }, [\n clientId,\n redirectUri,\n shouldAutoExchangeCode,\n config.clientSecret,\n config.scopes?.join(','),\n request?.codeVerifier,\n result,\n ]);\n\n return [request, fullResult, promptAsync];\n}\n"]}
|
|
@@ -20,8 +20,6 @@ export function invariantClientId(idName, value, providerName) {
|
|
|
20
20
|
throw new Error(`Client Id property \`${idName}\` must be defined to use ${providerName} auth on this platform.`);
|
|
21
21
|
}
|
|
22
22
|
export function useProxyEnabled(redirectUriOptions) {
|
|
23
|
-
return useMemo(() => redirectUriOptions.useProxy ?? shouldUseProxy(), [
|
|
24
|
-
redirectUriOptions.useProxy,
|
|
25
|
-
]);
|
|
23
|
+
return useMemo(() => redirectUriOptions.useProxy ?? shouldUseProxy(), [redirectUriOptions.useProxy]);
|
|
26
24
|
}
|
|
27
25
|
//# sourceMappingURL=ProviderUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderUtils.js","sourceRoot":"","sources":["../../src/providers/ProviderUtils.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,UAAU,mBAAmB,CAAC,SAAmB,EAAE,EAAE,cAAwB;IACjF,sDAAsD;IACtD,oBAAoB;IACpB,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,MAAM,CAAC;QACrB,GAAG,EAAE,KAAK;QACV,oCAAoC;QACpC,OAAO,EAAE,SAAS,CAAC,oBAAoB,KAAK,oBAAoB,CAAC,WAAW;KAC7E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,KAAU,EAAE,YAAoB;IAChF,IAAI,OAAO,KAAK,KAAK,WAAW;QAC9B,8BAA8B;QAC9B,MAAM,IAAI,KAAK,CACb,wBAAwB,MAAM,6BAA6B,YAAY,yBAAyB,CACjG,CAAC;AACN,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,kBAAmE;IAEnE,OAAO,OAAO,
|
|
1
|
+
{"version":3,"file":"ProviderUtils.js","sourceRoot":"","sources":["../../src/providers/ProviderUtils.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,EAAE,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,UAAU,mBAAmB,CAAC,SAAmB,EAAE,EAAE,cAAwB;IACjF,sDAAsD;IACtD,oBAAoB;IACpB,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,MAAM,CAAC;QACrB,GAAG,EAAE,KAAK;QACV,oCAAoC;QACpC,OAAO,EAAE,SAAS,CAAC,oBAAoB,KAAK,oBAAoB,CAAC,WAAW;KAC7E,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAc,EAAE,KAAU,EAAE,YAAoB;IAChF,IAAI,OAAO,KAAK,KAAK,WAAW;QAC9B,8BAA8B;QAC9B,MAAM,IAAI,KAAK,CACb,wBAAwB,MAAM,6BAA6B,YAAY,yBAAyB,CACjG,CAAC;AACN,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,kBAAmE;IAEnE,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,kBAAkB,CAAC,QAAQ,IAAI,cAAc,EAAE,EACrD,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAC9B,CAAC;AACJ,CAAC","sourcesContent":["import Constants, { ExecutionEnvironment } from 'expo-constants';\nimport { useMemo } from 'react';\nimport { Platform } from 'react-native';\n\nimport { AuthSessionRedirectUriOptions } from '../AuthSession';\n\nexport function applyRequiredScopes(scopes: string[] = [], requiredScopes: string[]): string[] {\n // Add the required scopes for returning profile data.\n // Remove duplicates\n return [...new Set([...scopes, ...requiredScopes])];\n}\n\n// Only natively in the Expo client.\nexport function shouldUseProxy(): boolean {\n return Platform.select({\n web: false,\n // Use the proxy in the Expo client.\n default: Constants.executionEnvironment === ExecutionEnvironment.StoreClient,\n });\n}\n\nexport function invariantClientId(idName: string, value: any, providerName: string) {\n if (typeof value === 'undefined')\n // TODO(Bacon): Add learn more\n throw new Error(\n `Client Id property \\`${idName}\\` must be defined to use ${providerName} auth on this platform.`\n );\n}\n\nexport function useProxyEnabled(\n redirectUriOptions: Pick<AuthSessionRedirectUriOptions, 'useProxy'>\n): boolean {\n return useMemo(\n () => redirectUriOptions.useProxy ?? shouldUseProxy(),\n [redirectUriOptions.useProxy]\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-auth-session",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"description": "Expo module for browser-based authentication",
|
|
5
5
|
"main": "build/AuthSession.js",
|
|
6
6
|
"types": "build/AuthSession.d.ts",
|
|
@@ -32,12 +32,12 @@
|
|
|
32
32
|
},
|
|
33
33
|
"author": "650 Industries, Inc.",
|
|
34
34
|
"license": "MIT",
|
|
35
|
-
"homepage": "https://docs.expo.
|
|
35
|
+
"homepage": "https://docs.expo.dev/versions/latest/sdk/auth-session",
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"expo-constants": "~
|
|
38
|
-
"expo-crypto": "~
|
|
39
|
-
"expo-linking": "~2.
|
|
40
|
-
"expo-web-browser": "~
|
|
37
|
+
"expo-constants": "~12.0.0",
|
|
38
|
+
"expo-crypto": "~10.0.0",
|
|
39
|
+
"expo-linking": "~2.4.0",
|
|
40
|
+
"expo-web-browser": "~10.0.0",
|
|
41
41
|
"invariant": "^2.2.4",
|
|
42
42
|
"qs": "6.9.1"
|
|
43
43
|
},
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"jest": {
|
|
57
57
|
"preset": "expo-module-scripts"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "1fffde73411ee7a642b98f1506a8de921805d52b"
|
|
60
60
|
}
|
package/src/AuthRequestHooks.ts
CHANGED
|
@@ -14,9 +14,16 @@ export function useAutoDiscovery(issuerOrDiscovery: IssuerOrDiscovery): Discover
|
|
|
14
14
|
const [discovery, setDiscovery] = useState<DiscoveryDocument | null>(null);
|
|
15
15
|
|
|
16
16
|
useEffect(() => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
let isAllowed = true;
|
|
18
|
+
resolveDiscoveryAsync(issuerOrDiscovery).then((discovery) => {
|
|
19
|
+
if (isAllowed) {
|
|
20
|
+
setDiscovery(discovery);
|
|
21
|
+
}
|
|
19
22
|
});
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
isAllowed = false;
|
|
26
|
+
};
|
|
20
27
|
}, [issuerOrDiscovery]);
|
|
21
28
|
|
|
22
29
|
return discovery;
|
|
@@ -29,9 +36,10 @@ export function useLoadedAuthRequest(
|
|
|
29
36
|
): AuthRequest | null {
|
|
30
37
|
const [request, setRequest] = useState<AuthRequest | null>(null);
|
|
31
38
|
const scopeString = useMemo(() => config.scopes?.join(','), [config.scopes]);
|
|
32
|
-
const extraParamsString = useMemo(
|
|
33
|
-
config.extraParams,
|
|
34
|
-
|
|
39
|
+
const extraParamsString = useMemo(
|
|
40
|
+
() => JSON.stringify(config.extraParams || {}),
|
|
41
|
+
[config.extraParams]
|
|
42
|
+
);
|
|
35
43
|
useEffect(
|
|
36
44
|
() => {
|
|
37
45
|
let isMounted = true;
|
package/src/AuthSession.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Platform } from '@unimodules/core';
|
|
2
1
|
import Constants, { ExecutionEnvironment } from 'expo-constants';
|
|
3
2
|
import * as Linking from 'expo-linking';
|
|
3
|
+
import { Platform } from 'expo-modules-core';
|
|
4
4
|
import { dismissAuthSession, openAuthSessionAsync } from 'expo-web-browser';
|
|
5
5
|
|
|
6
6
|
import { AuthRequest } from './AuthRequest';
|
package/src/Errors.ts
CHANGED
package/src/Fetch.ts
CHANGED
package/src/PKCE.ts
CHANGED
|
@@ -26,10 +26,7 @@ function convertBufferToString(buffer: Uint8Array): string {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function convertToUrlSafeString(b64: string): string {
|
|
29
|
-
return b64
|
|
30
|
-
.replace(/\+/g, '-')
|
|
31
|
-
.replace(/\//g, '_')
|
|
32
|
-
.replace(/=/g, '');
|
|
29
|
+
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
export function generateRandom(size: number): string {
|
package/src/QueryParams.ts
CHANGED
|
@@ -5,9 +5,10 @@ export function buildQueryString(input: Record<string, string>): string {
|
|
|
5
5
|
return qs.stringify(input);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export function getQueryParams(
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export function getQueryParams(url: string): {
|
|
9
|
+
errorCode: string | null;
|
|
10
|
+
params: { [key: string]: string };
|
|
11
|
+
} {
|
|
11
12
|
const parts = url.split('#');
|
|
12
13
|
const hash = parts[1];
|
|
13
14
|
const partsWithoutHash = parts[0].split('?');
|
|
@@ -5,8 +5,6 @@ import { CreateURLOptions } from 'expo-linking';
|
|
|
5
5
|
import { resolveScheme } from 'expo-linking/build/Schemes';
|
|
6
6
|
import qs, { ParsedQs } from 'qs';
|
|
7
7
|
|
|
8
|
-
const { manifest } = Constants;
|
|
9
|
-
|
|
10
8
|
export class SessionUrlProvider {
|
|
11
9
|
private static readonly BASE_URL = `https://auth.expo.io`;
|
|
12
10
|
private static readonly SESSION_PATH = 'expo-auth-session';
|
|
@@ -49,14 +47,17 @@ export class SessionUrlProvider {
|
|
|
49
47
|
}
|
|
50
48
|
}
|
|
51
49
|
|
|
52
|
-
const legacyExpoProjectId =
|
|
50
|
+
const legacyExpoProjectId =
|
|
51
|
+
Constants.manifest?.originalFullName ||
|
|
52
|
+
Constants.manifest2?.extra?.expoClient?.originalFullName ||
|
|
53
|
+
Constants.manifest?.id;
|
|
53
54
|
|
|
54
55
|
if (!legacyExpoProjectId) {
|
|
55
56
|
let nextSteps = '';
|
|
56
57
|
if (__DEV__) {
|
|
57
58
|
if (Constants.executionEnvironment === ExecutionEnvironment.Bare) {
|
|
58
59
|
nextSteps =
|
|
59
|
-
' Please ensure you have the latest version of expo-constants installed and rebuild your native app. You can verify that
|
|
60
|
+
' Please ensure you have the latest version of expo-constants installed and rebuild your native app. You can verify that originalFullName is defined by running `expo config --type public` and inspecting the output.';
|
|
60
61
|
} else if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {
|
|
61
62
|
nextSteps =
|
|
62
63
|
' Please report this as a bug with the contents of `expo config --type public`.';
|
|
@@ -76,7 +77,8 @@ export class SessionUrlProvider {
|
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
private static getHostAddressQueryParams(): ParsedQs | undefined {
|
|
79
|
-
let hostUri: string =
|
|
80
|
+
let hostUri: string | undefined =
|
|
81
|
+
Constants.manifest?.hostUri ?? Constants.manifest2?.extra?.expoClient?.hostUri;
|
|
80
82
|
if (
|
|
81
83
|
!hostUri &&
|
|
82
84
|
(ExecutionEnvironment.StoreClient === Constants.executionEnvironment || resolveScheme({}))
|
|
@@ -90,6 +92,10 @@ export class SessionUrlProvider {
|
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
if (!hostUri) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
93
99
|
const uriParts = hostUri?.split('?');
|
|
94
100
|
try {
|
|
95
101
|
return qs.parse(uriParts?.[1]);
|