mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-30 04:28:19 +02:00
PM-4954 Migrate SSO Component
This commit is contained in:
parent
8e97c1c8e4
commit
eff467a345
@ -1,52 +1,22 @@
|
|||||||
<form
|
<form [formGroup]="formGroup" [bitSubmit]="submit" class="tw-container">
|
||||||
#form
|
<div *ngIf="loggingIn" class="tw-w-[400px]">
|
||||||
(ngSubmit)="submit()"
|
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
||||||
class="container"
|
{{ "loading" | i18n }}
|
||||||
[appApiAction]="initiateSsoFormPromise"
|
</div>
|
||||||
ngNativeValidate
|
<div *ngIf="!loggingIn" class="tw-w-[400px]">
|
||||||
>
|
<p bitTypography="body1">{{ "ssoLogInWithOrgIdentifier" | i18n }}</p>
|
||||||
<div class="row justify-content-md-center mt-5">
|
<bit-form-field>
|
||||||
<div class="col-5">
|
<bit-label>{{ "ssoIdentifier" | i18n }}</bit-label>
|
||||||
<img class="logo mb-2 logo-themed" alt="Bitwarden" />
|
<input bitInput type="text" formControlName="identifier" appAutofocus />
|
||||||
<div class="card d-block mt-4">
|
</bit-form-field>
|
||||||
<div class="card-body" *ngIf="loggingIn">
|
<hr />
|
||||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
<div class="tw-flex tw-gap-2">
|
||||||
{{ "loading" | i18n }}
|
<button type="submit" bitButton bitFormButton buttonType="primary" [block]="true">
|
||||||
</div>
|
{{ "logIn" | i18n }}
|
||||||
<div class="card-body" *ngIf="!loggingIn">
|
</button>
|
||||||
<p>{{ "ssoLogInWithOrgIdentifier" | i18n }}</p>
|
<a bitButton buttonType="secondary" routerLink="/login" [block]="true">
|
||||||
<div class="form-group">
|
{{ "cancel" | i18n }}
|
||||||
<label for="identifier">{{ "ssoIdentifier" | i18n }}</label>
|
</a>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
|
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
@ -31,6 +32,10 @@ import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/ge
|
|||||||
})
|
})
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||||
export class SsoComponent extends BaseSsoComponent {
|
export class SsoComponent extends BaseSsoComponent {
|
||||||
|
protected formGroup = new FormGroup({
|
||||||
|
identifier: new FormControl(null, [Validators.required]),
|
||||||
|
});
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ssoLoginService: SsoLoginServiceAbstraction,
|
ssoLoginService: SsoLoginServiceAbstraction,
|
||||||
loginStrategyService: LoginStrategyServiceAbstraction,
|
loginStrategyService: LoginStrategyServiceAbstraction,
|
||||||
@ -82,7 +87,7 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
||||||
if (qParams.identifier != null) {
|
if (qParams.identifier != null) {
|
||||||
// SSO Org Identifier in query params takes precedence over claimed domains
|
// SSO Org Identifier in query params takes precedence over claimed domains
|
||||||
this.identifier = qParams.identifier;
|
this.formGroup.get("identifier").setValue(qParams.identifier);
|
||||||
} else {
|
} else {
|
||||||
// Note: this flow is written for web but both browser and desktop
|
// Note: this flow is written for web but both browser and desktop
|
||||||
// redirect here on SSO button click.
|
// redirect here on SSO button click.
|
||||||
@ -96,7 +101,7 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
|
await this.orgDomainApiService.getClaimedOrgDomainByEmail(qParams.email);
|
||||||
|
|
||||||
if (response?.ssoAvailable) {
|
if (response?.ssoAvailable) {
|
||||||
this.identifier = response.organizationIdentifier;
|
this.formGroup.get("identifier").setValue(response.organizationIdentifier);
|
||||||
await this.submit();
|
await this.submit();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -110,7 +115,7 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
// Fallback to state svc if domain is unclaimed
|
// Fallback to state svc if domain is unclaimed
|
||||||
const storedIdentifier = await this.ssoLoginService.getOrganizationSsoIdentifier();
|
const storedIdentifier = await this.ssoLoginService.getOrganizationSsoIdentifier();
|
||||||
if (storedIdentifier != null) {
|
if (storedIdentifier != null) {
|
||||||
this.identifier = storedIdentifier;
|
this.formGroup.get("identifier").setValue(storedIdentifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -131,13 +136,12 @@ export class SsoComponent extends BaseSsoComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
submit = async () => {
|
||||||
await this.ssoLoginService.setOrganizationSsoIdentifier(this.identifier);
|
this.identifier = this.formGroup.value.identifier;
|
||||||
|
await this.ssoLoginService.setOrganizationSsoIdentifier(this.formGroup.value.identifier);
|
||||||
if (this.clientId === "browser") {
|
if (this.clientId === "browser") {
|
||||||
document.cookie = `ssoHandOffMessage=${this.i18nService.t("ssoHandOff")};SameSite=strict`;
|
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.
|
await Object.getPrototypeOf(this).submit.call(this);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
};
|
||||||
super.submit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import { VerifyRecoverDeleteProviderComponent } from "./admin-console/providers/
|
|||||||
import { CreateOrganizationComponent } from "./admin-console/settings/create-organization.component";
|
import { CreateOrganizationComponent } from "./admin-console/settings/create-organization.component";
|
||||||
import { SponsoredFamiliesComponent } from "./admin-console/settings/sponsored-families.component";
|
import { SponsoredFamiliesComponent } from "./admin-console/settings/sponsored-families.component";
|
||||||
import { AcceptOrganizationComponent } from "./auth/accept-organization.component";
|
import { AcceptOrganizationComponent } from "./auth/accept-organization.component";
|
||||||
|
import { AnonLayoutWrapperComponent } from "./auth/anon-layout-wrapper.component";
|
||||||
import { deepLinkGuard } from "./auth/guards/deep-link.guard";
|
import { deepLinkGuard } from "./auth/guards/deep-link.guard";
|
||||||
import { HintComponent } from "./auth/hint.component";
|
import { HintComponent } from "./auth/hint.component";
|
||||||
import { LockComponent } from "./auth/lock.component";
|
import { LockComponent } from "./auth/lock.component";
|
||||||
@ -94,12 +95,6 @@ const routes: Routes = [
|
|||||||
redirectTo: "register",
|
redirectTo: "register",
|
||||||
pathMatch: "full",
|
pathMatch: "full",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "sso",
|
|
||||||
component: SsoComponent,
|
|
||||||
canActivate: [UnauthGuard],
|
|
||||||
data: { titleId: "enterpriseSingleSignOn" },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "set-password",
|
path: "set-password",
|
||||||
component: SetPasswordComponent,
|
component: SetPasswordComponent,
|
||||||
@ -295,6 +290,19 @@ const routes: Routes = [
|
|||||||
loadChildren: () =>
|
loadChildren: () =>
|
||||||
import("./admin-console/organizations/organization.module").then((m) => m.OrganizationModule),
|
import("./admin-console/organizations/organization.module").then((m) => m.OrganizationModule),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
component: AnonLayoutWrapperComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "sso",
|
||||||
|
component: SsoComponent,
|
||||||
|
data: {
|
||||||
|
pageTitle: "enterpriseSingleSignOn",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
Loading…
Reference in New Issue
Block a user