in src/auth/auth-config.ts [1277:1399]
public static validate(options: Partial<OIDCAuthProviderConfig>, ignoreMissingFields = false): void {
const validKeys = {
enabled: true,
displayName: true,
providerId: true,
clientId: true,
issuer: true,
clientSecret: true,
responseType: true,
};
const validResponseTypes = {
idToken: true,
code: true,
};
if (!validator.isNonNullObject(options)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
'"OIDCAuthProviderConfig" must be a valid non-null object.',
);
}
// Check for unsupported top level attributes.
for (const key in options) {
if (!(key in validKeys)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
`"${key}" is not a valid OIDC config parameter.`,
);
}
}
// Required fields.
if (validator.isNonEmptyString(options.providerId)) {
if (options.providerId.indexOf('oidc.') !== 0) {
throw new FirebaseAuthError(
!options.providerId ? AuthClientErrorCode.MISSING_PROVIDER_ID : AuthClientErrorCode.INVALID_PROVIDER_ID,
'"OIDCAuthProviderConfig.providerId" must be a valid non-empty string prefixed with "oidc.".',
);
}
} else if (!ignoreMissingFields) {
throw new FirebaseAuthError(
!options.providerId ? AuthClientErrorCode.MISSING_PROVIDER_ID : AuthClientErrorCode.INVALID_PROVIDER_ID,
'"OIDCAuthProviderConfig.providerId" must be a valid non-empty string prefixed with "oidc.".',
);
}
if (!(ignoreMissingFields && typeof options.clientId === 'undefined') &&
!validator.isNonEmptyString(options.clientId)) {
throw new FirebaseAuthError(
!options.clientId ? AuthClientErrorCode.MISSING_OAUTH_CLIENT_ID : AuthClientErrorCode.INVALID_OAUTH_CLIENT_ID,
'"OIDCAuthProviderConfig.clientId" must be a valid non-empty string.',
);
}
if (!(ignoreMissingFields && typeof options.issuer === 'undefined') &&
!validator.isURL(options.issuer)) {
throw new FirebaseAuthError(
!options.issuer ? AuthClientErrorCode.MISSING_ISSUER : AuthClientErrorCode.INVALID_CONFIG,
'"OIDCAuthProviderConfig.issuer" must be a valid URL string.',
);
}
if (typeof options.enabled !== 'undefined' &&
!validator.isBoolean(options.enabled)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
'"OIDCAuthProviderConfig.enabled" must be a boolean.',
);
}
if (typeof options.displayName !== 'undefined' &&
!validator.isString(options.displayName)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
'"OIDCAuthProviderConfig.displayName" must be a valid string.',
);
}
if (typeof options.clientSecret !== 'undefined' &&
!validator.isNonEmptyString(options.clientSecret)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
'"OIDCAuthProviderConfig.clientSecret" must be a valid string.',
);
}
if (validator.isNonNullObject(options.responseType) && typeof options.responseType !== 'undefined') {
Object.keys(options.responseType).forEach((key) => {
if (!(key in validResponseTypes)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_CONFIG,
`"${key}" is not a valid OAuthResponseType parameter.`,
);
}
});
const idToken = options.responseType.idToken;
if (typeof idToken !== 'undefined' && !validator.isBoolean(idToken)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_ARGUMENT,
'"OIDCAuthProviderConfig.responseType.idToken" must be a boolean.',
);
}
const code = options.responseType.code;
if (typeof code !== 'undefined') {
if (!validator.isBoolean(code)) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_ARGUMENT,
'"OIDCAuthProviderConfig.responseType.code" must be a boolean.',
);
}
// If code flow is enabled, client secret must be provided.
if (code && typeof options.clientSecret === 'undefined') {
throw new FirebaseAuthError(
AuthClientErrorCode.MISSING_OAUTH_CLIENT_SECRET,
'The OAuth configuration client secret is required to enable OIDC code flow.',
);
}
}
const allKeys = Object.keys(options.responseType).length;
const enabledCount = Object.values(options.responseType).filter(Boolean).length;
// Only one of OAuth response types can be set to true.
if (allKeys > 1 && enabledCount != 1) {
throw new FirebaseAuthError(
AuthClientErrorCode.INVALID_OAUTH_RESPONSETYPE,
'Only exactly one OAuth responseType should be set to true.',
);
}
}
}