1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-10-04 05:08:06 +02:00

PM-4954 Migrate SSO Component (#9126)

* PM-4954 Migrate SSO Component

* PM-4954 Updated anon layout changes

* PM-4954 Updated oss routing module

* PM-4954 Addressed review comments

* PM-4954 - SSO Comp - adjust to use form control accessor.

* PM-4954 - SsoComp - update form control accessor to use type safe approach.

* PM-4954 - Move canActivate up a level

* PM-4954 - Consolidate route under AnonLayoutWrapperComponent path after merging in main.

---------

Co-authored-by: Jared Snider <jsnider@bitwarden.com>
Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
This commit is contained in:
KiruthigaManivannan 2024-06-12 19:46:58 +05:30 committed by GitHub
parent c726b91c1f
commit dd5d01283e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 54 additions and 63 deletions

View File

@ -1,52 +1,22 @@
<form
#form
(ngSubmit)="submit()"
class="container"
[appApiAction]="initiateSsoFormPromise"
ngNativeValidate
>
<div class="row justify-content-md-center mt-5">
<div class="col-5">
<img class="logo mb-2 logo-themed" alt="Bitwarden" />
<div class="card d-block mt-4">
<div class="card-body" *ngIf="loggingIn">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
{{ "loading" | i18n }}
</div>
<div class="card-body" *ngIf="!loggingIn">
<p>{{ "ssoLogInWithOrgIdentifier" | i18n }}</p>
<div class="form-group">
<label for="identifier">{{ "ssoIdentifier" | i18n }}</label>
<input
id="identifier"
class="form-control"
type="text"
name="Identifier"
[(ngModel)]="identifier"
required
appAutofocus
/>
</div>
<hr />
<div class="d-flex">
<button
type="submit"
class="btn btn-primary btn-block btn-submit"
[disabled]="form.loading"
>
<span> <i class="bwi bwi-sign-in" aria-hidden="true"></i> {{ "logIn" | i18n }} </span>
<i
class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}"
aria-hidden="true"
></i>
</button>
<a routerLink="/login" class="btn btn-outline-secondary btn-block ml-2 mt-0">
{{ "cancel" | i18n }}
</a>
</div>
</div>
</div>
<form [formGroup]="formGroup" [bitSubmit]="submit" class="tw-container">
<div *ngIf="loggingIn">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
{{ "loading" | i18n }}
</div>
<div *ngIf="!loggingIn">
<p bitTypography="body1">{{ "ssoLogInWithOrgIdentifier" | i18n }}</p>
<bit-form-field>
<bit-label>{{ "ssoIdentifier" | i18n }}</bit-label>
<input bitInput type="text" formControlName="identifier" appAutofocus />
</bit-form-field>
<hr />
<div class="tw-flex tw-gap-2">
<button type="submit" bitButton bitFormButton buttonType="primary" [block]="true">
{{ "logIn" | i18n }}
</button>
<a bitButton buttonType="secondary" routerLink="/login" [block]="true">
{{ "cancel" | i18n }}
</a>
</div>
</div>
</form>

View File

@ -1,4 +1,5 @@
import { Component } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";
import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators";
@ -31,6 +32,14 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class SsoComponent extends BaseSsoComponent {
protected formGroup = new FormGroup({
identifier: new FormControl(null, [Validators.required]),
});
get identifierFormControl() {
return this.formGroup.controls.identifier;
}
constructor(
ssoLoginService: SsoLoginServiceAbstraction,
loginStrategyService: LoginStrategyServiceAbstraction,
@ -82,7 +91,7 @@ export class SsoComponent extends BaseSsoComponent {
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
if (qParams.identifier != null) {
// SSO Org Identifier in query params takes precedence over claimed domains
this.identifier = qParams.identifier;
this.identifierFormControl.setValue(qParams.identifier);
} else {
// Note: this flow is written for web but both browser and desktop
// redirect here on SSO button click.
@ -96,7 +105,7 @@ export class SsoComponent extends BaseSsoComponent {
await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
if (response?.ssoAvailable) {
this.identifier = response.organizationIdentifier;
this.identifierFormControl.setValue(response.organizationIdentifier);
await this.submit();
return;
}
@ -110,7 +119,7 @@ export class SsoComponent extends BaseSsoComponent {
// Fallback to state svc if domain is unclaimed
const storedIdentifier = await this.ssoLoginService.getOrganizationSsoIdentifier();
if (storedIdentifier != null) {
this.identifier = storedIdentifier;
this.identifierFormControl.setValue(storedIdentifier);
}
}
});
@ -131,13 +140,12 @@ export class SsoComponent extends BaseSsoComponent {
}
}
async submit() {
submit = async () => {
this.identifier = this.identifierFormControl.value;
await this.ssoLoginService.setOrganizationSsoIdentifier(this.identifier);
if (this.clientId === "browser") {
document.cookie = `ssoHandOffMessage=${this.i18nService.t("ssoHandOff")};SameSite=strict`;
}
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
super.submit();
}
await Object.getPrototypeOf(this).submit.call(this);
};
}

View File

@ -97,12 +97,6 @@ const routes: Routes = [
redirectTo: "register",
pathMatch: "full",
},
{
path: "sso",
component: SsoComponent,
canActivate: [UnauthGuard],
data: { titleId: "enterpriseSingleSignOn" } satisfies DataProperties,
},
{
path: "set-password",
component: SetPasswordComponent,
@ -181,6 +175,25 @@ const routes: Routes = [
path: "",
component: AnonLayoutWrapperComponent,
children: [
{
path: "sso",
canActivate: [unauthGuardFn()],
children: [
{
path: "",
component: SsoComponent,
data: {
pageTitle: "enterpriseSingleSignOn",
titleId: "enterpriseSingleSignOn",
} satisfies DataProperties & AnonLayoutWrapperData,
},
{
path: "",
component: EnvironmentSelectorComponent,
outlet: "environment-selector",
},
],
},
{
path: "login",
canActivate: [unauthGuardFn()],