mirror of
https://github.com/bitwarden/browser
synced 2025-12-21 18:53:29 +00:00
[PM-17751] Store SSO email in state on web client (#13295)
* Moved saving of SSO email outside of browser/desktop code * Clarified comments. * Tests * Refactored login component services to manage state * Fixed input on login component * Fixed tests * Linting * Moved web setting in state into web override * updated tests * Fixed typing. * Fixed type safety issues. * Added comments and renamed for clarity. * Removed method parameters that weren't used * Added clarifying comments * Added more comments. * Removed test that is not necessary on base * Test cleanup * More comments. * Linting * Fixed test. * Fixed base URL * Fixed typechecking. * Type checking * Moved setting of email state to default service * Added comments. * Consolidated SSO URL formatting * Updated comment * Fixed reference. * Fixed missing parameter. * Initialized service. * Added comments * Added initialization of new service * Made email optional due to CLI. * Fixed comment on handleSsoClick. * Added SSO email persistence to v1 component. --------- Co-authored-by: Bernd Schoolmann <mail@quexten.com>
This commit is contained in:
@@ -6,3 +6,4 @@ export * from "./auth-request/auth-request.service";
|
||||
export * from "./auth-request/auth-request-api.service";
|
||||
export * from "./accounts/lock.service";
|
||||
export * from "./login-success-handler/default-login-success-handler.service";
|
||||
export * from "./sso-redirect/sso-url.service";
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { ClientType } from "@bitwarden/common/enums";
|
||||
|
||||
import { DESKTOP_SSO_CALLBACK, SsoUrlService } from "./sso-url.service";
|
||||
|
||||
describe("SsoUrlService", () => {
|
||||
let service: SsoUrlService;
|
||||
|
||||
beforeEach(() => {
|
||||
service = new SsoUrlService();
|
||||
});
|
||||
|
||||
it("should build Desktop SSO URL correctly", () => {
|
||||
const baseUrl = "https://web-vault.bitwarden.com";
|
||||
const clientType = ClientType.Desktop;
|
||||
const redirectUri = DESKTOP_SSO_CALLBACK;
|
||||
const state = "abc123";
|
||||
const codeChallenge = "xyz789";
|
||||
const email = "test@bitwarden.com";
|
||||
|
||||
const expectedUrl = `${baseUrl}/#/sso?clientId=desktop&redirectUri=${encodeURIComponent(redirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}`;
|
||||
|
||||
const result = service.buildSsoUrl(
|
||||
baseUrl,
|
||||
clientType,
|
||||
redirectUri,
|
||||
state,
|
||||
codeChallenge,
|
||||
email,
|
||||
);
|
||||
expect(result).toBe(expectedUrl);
|
||||
});
|
||||
|
||||
it("should build Desktop localhost callback SSO URL correctly", () => {
|
||||
const baseUrl = "https://web-vault.bitwarden.com";
|
||||
const clientType = ClientType.Desktop;
|
||||
const redirectUri = `https://localhost:1000`;
|
||||
const state = "abc123";
|
||||
const codeChallenge = "xyz789";
|
||||
const email = "test@bitwarden.com";
|
||||
|
||||
const expectedUrl = `${baseUrl}/#/sso?clientId=desktop&redirectUri=${encodeURIComponent(redirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}`;
|
||||
|
||||
const result = service.buildSsoUrl(
|
||||
baseUrl,
|
||||
clientType,
|
||||
redirectUri,
|
||||
state,
|
||||
codeChallenge,
|
||||
email,
|
||||
);
|
||||
expect(result).toBe(expectedUrl);
|
||||
});
|
||||
|
||||
it("should build Extension SSO URL correctly", () => {
|
||||
const baseUrl = "https://web-vault.bitwarden.com";
|
||||
const clientType = ClientType.Browser;
|
||||
const redirectUri = baseUrl + "/sso-connector.html";
|
||||
const state = "abc123";
|
||||
const codeChallenge = "xyz789";
|
||||
const email = "test@bitwarden.com";
|
||||
|
||||
const expectedUrl = `${baseUrl}/#/sso?clientId=browser&redirectUri=${encodeURIComponent(redirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}`;
|
||||
|
||||
const result = service.buildSsoUrl(
|
||||
baseUrl,
|
||||
clientType,
|
||||
redirectUri,
|
||||
state,
|
||||
codeChallenge,
|
||||
email,
|
||||
);
|
||||
expect(result).toBe(expectedUrl);
|
||||
});
|
||||
|
||||
it("should build CLI SSO URL correctly", () => {
|
||||
const baseUrl = "https://web-vault.bitwarden.com";
|
||||
const clientType = ClientType.Cli;
|
||||
const redirectUri = "https://localhost:1000";
|
||||
const state = "abc123";
|
||||
const codeChallenge = "xyz789";
|
||||
const email = "test@bitwarden.com";
|
||||
|
||||
const expectedUrl = `${baseUrl}/#/sso?clientId=cli&redirectUri=${encodeURIComponent(redirectUri)}&state=${state}&codeChallenge=${codeChallenge}&email=${encodeURIComponent(email)}`;
|
||||
|
||||
const result = service.buildSsoUrl(
|
||||
baseUrl,
|
||||
clientType,
|
||||
redirectUri,
|
||||
state,
|
||||
codeChallenge,
|
||||
email,
|
||||
);
|
||||
expect(result).toBe(expectedUrl);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { ClientType } from "@bitwarden/common/enums";
|
||||
|
||||
export const DESKTOP_SSO_CALLBACK: string = "bitwarden://sso-callback";
|
||||
|
||||
export class SsoUrlService {
|
||||
/**
|
||||
* Builds a URL for redirecting users to the web app SSO component to complete SSO
|
||||
* @param webAppUrl The URL of the web app
|
||||
* @param clientType The client type that is initiating SSO, which will drive how the response is handled
|
||||
* @param redirectUri The redirect URI or callback that will receive the SSO code after authentication
|
||||
* @param state A state value that will be peristed through the SSO flow
|
||||
* @param codeChallenge A challenge value that will be used to verify the SSO code after authentication
|
||||
* @param email The optional email adddress of the user initiating SSO, which will be used to look up the org SSO identifier
|
||||
* @returns The URL for redirecting users to the web app SSO component
|
||||
*/
|
||||
buildSsoUrl(
|
||||
webAppUrl: string,
|
||||
clientType: ClientType,
|
||||
redirectUri: string,
|
||||
state: string,
|
||||
codeChallenge: string,
|
||||
email?: string,
|
||||
): string {
|
||||
let url =
|
||||
webAppUrl +
|
||||
"/#/sso?clientId=" +
|
||||
clientType +
|
||||
"&redirectUri=" +
|
||||
encodeURIComponent(redirectUri) +
|
||||
"&state=" +
|
||||
state +
|
||||
"&codeChallenge=" +
|
||||
codeChallenge;
|
||||
|
||||
if (email) {
|
||||
url += "&email=" + encodeURIComponent(email);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user