voluptasmollitia
Version:
Monorepo for the Firebase JavaScript SDK
157 lines (146 loc) • 4.75 kB
text/typescript
/**
* @license
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
AdditionalUserInfo,
ProviderId,
UserCredential
} from '../../model/public_types';
import { IdTokenResponse, IdTokenResponseKind } from '../../model/id_token';
import { _parseToken } from './id_token_result';
import { UserCredentialInternal } from '../../model/user';
/**
* Parse the `AdditionalUserInfo` from the ID token response.
*
*/
export function _fromIdTokenResponse(
idTokenResponse?: IdTokenResponse
): AdditionalUserInfo | null {
if (!idTokenResponse) {
return null;
}
const { providerId } = idTokenResponse;
const profile = idTokenResponse.rawUserInfo
? JSON.parse(idTokenResponse.rawUserInfo)
: {};
const isNewUser =
idTokenResponse.isNewUser ||
idTokenResponse.kind === IdTokenResponseKind.SignupNewUser;
if (!providerId && idTokenResponse?.idToken) {
const signInProvider = _parseToken(idTokenResponse.idToken)?.firebase?.[
'sign_in_provider'
];
if (signInProvider) {
const filteredProviderId =
signInProvider !== ProviderId.ANONYMOUS &&
signInProvider !== ProviderId.CUSTOM
? (signInProvider as ProviderId)
: null;
// Uses generic class in accordance with the legacy SDK.
return new GenericAdditionalUserInfo(isNewUser, filteredProviderId);
}
}
if (!providerId) {
return null;
}
switch (providerId) {
case ProviderId.FACEBOOK:
return new FacebookAdditionalUserInfo(isNewUser, profile);
case ProviderId.GITHUB:
return new GithubAdditionalUserInfo(isNewUser, profile);
case ProviderId.GOOGLE:
return new GoogleAdditionalUserInfo(isNewUser, profile);
case ProviderId.TWITTER:
return new TwitterAdditionalUserInfo(
isNewUser,
profile,
idTokenResponse.screenName || null
);
case ProviderId.CUSTOM:
case ProviderId.ANONYMOUS:
return new GenericAdditionalUserInfo(isNewUser, null);
default:
return new GenericAdditionalUserInfo(isNewUser, providerId, profile);
}
}
class GenericAdditionalUserInfo implements AdditionalUserInfo {
constructor(
readonly isNewUser: boolean,
readonly providerId: ProviderId | string | null,
readonly profile: Record<string, unknown> = {}
) {}
}
class FederatedAdditionalUserInfoWithUsername extends GenericAdditionalUserInfo {
constructor(
isNewUser: boolean,
providerId: ProviderId,
profile: Record<string, unknown>,
readonly username: string | null
) {
super(isNewUser, providerId, profile);
}
}
class FacebookAdditionalUserInfo extends GenericAdditionalUserInfo {
constructor(isNewUser: boolean, profile: Record<string, unknown>) {
super(isNewUser, ProviderId.FACEBOOK, profile);
}
}
class GithubAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
constructor(isNewUser: boolean, profile: Record<string, unknown>) {
super(
isNewUser,
ProviderId.GITHUB,
profile,
typeof profile?.login === 'string' ? profile?.login : null
);
}
}
class GoogleAdditionalUserInfo extends GenericAdditionalUserInfo {
constructor(isNewUser: boolean, profile: Record<string, unknown>) {
super(isNewUser, ProviderId.GOOGLE, profile);
}
}
class TwitterAdditionalUserInfo extends FederatedAdditionalUserInfoWithUsername {
constructor(
isNewUser: boolean,
profile: Record<string, unknown>,
screenName: string | null
) {
super(isNewUser, ProviderId.TWITTER, profile, screenName);
}
}
/**
* Extracts provider specific {@link AdditionalUserInfo} for the given credential.
*
* @param userCredential - The user credential.
*
* @public
*/
export function getAdditionalUserInfo(
userCredential: UserCredential
): AdditionalUserInfo | null {
const { user, _tokenResponse } = userCredential as UserCredentialInternal;
if (user.isAnonymous && !_tokenResponse) {
// Handle the special case where signInAnonymously() gets called twice.
// No network call is made so there's nothing to actually fill this in
return {
providerId: null,
isNewUser: false,
profile: null
};
}
return _fromIdTokenResponse(_tokenResponse);
}