Skip to content

Commit f51fef7

Browse files
committed
adding endpoint to get provider id for org slug
1 parent b54eb2b commit f51fef7

File tree

7 files changed

+52
-5
lines changed

7 files changed

+52
-5
lines changed

components/dashboard/src/login/SSOLoginForm.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,23 @@
66

77
import { useMutation } from "@tanstack/react-query";
88
import { FC, useCallback, useState } from "react";
9+
import Alert from "../components/Alert";
910
import { Button } from "../components/Button";
1011
import { TextInputField } from "../components/forms/TextInputField";
12+
import { getGitpodService } from "../service/service";
1113

1214
export const SSOLoginForm: FC = () => {
1315
const [orgSlug, setOrgSlug] = useState("");
16+
const [error, setError] = useState("");
17+
1418
// TODO: remove this
1519
const [loginUrl, setLoginUrl] = useState("");
1620

1721
const exchangeSlug = useMutation({
1822
mutationFn: async ({ slug }: { slug: string }) => {
1923
// make api call to get provider id by slug
2024
// return provider id
21-
await new Promise((resolve) => setTimeout(resolve, 2000));
22-
23-
return { id: "sample-id" };
25+
return await getGitpodService().server.getSSOLoginID(slug);
2426
},
2527
});
2628

@@ -29,10 +31,16 @@ export const SSOLoginForm: FC = () => {
2931
e.preventDefault();
3032

3133
// make api call to get provider id by slug
32-
const { id } = await exchangeSlug.mutateAsync({ slug: orgSlug });
34+
const resp = await exchangeSlug.mutateAsync({ slug: orgSlug });
35+
const loginId = resp?.id;
36+
37+
// No SSO configured for provided slug
38+
if (!loginId) {
39+
setError("It looks like SSO has not been configured for that organization.");
40+
}
3341

3442
// create sso login url with provider id
35-
const loginUrl = `/oidc/start/?id=${id}`;
43+
const loginUrl = `/oidc/start/?id=${loginId}`;
3644
setLoginUrl(loginUrl);
3745

3846
// openAuthorize window for sso w/ login url
@@ -49,6 +57,7 @@ export const SSOLoginForm: FC = () => {
4957
Continue with SSO
5058
</Button>
5159
{loginUrl && <p>{loginUrl}</p>}
60+
{error && <Alert type="info">{error}</Alert>}
5261
</div>
5362
</form>
5463
);

components/gitpod-db/src/auth-provider-entry-db.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface AuthProviderEntryDB {
2121
findAllHosts(): Promise<string[]>;
2222
findByHost(host: string): Promise<AuthProviderEntry | undefined>;
2323
findById(id: string): Promise<AuthProviderEntry | undefined>;
24+
findByOrgSlug(slug: string): Promise<AuthProviderEntry | undefined>;
2425
findByUserId(userId: string): Promise<AuthProviderEntry[]>;
2526
findByOrgId(organizationId: string): Promise<AuthProviderEntry[]>;
2627
}

components/gitpod-db/src/typeorm/auth-provider-entry-db-impl.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { AuthProviderEntry } from "@gitpod/gitpod-protocol";
1111
import { AuthProviderEntryDB } from "../auth-provider-entry-db";
1212
import { DBAuthProviderEntry } from "./entity/db-auth-provider-entry";
1313
import { DBIdentity } from "./entity/db-identity";
14+
import { DBTeam } from "./entity/db-team";
1415
import { createHash } from "crypto";
1516

1617
@injectable()
@@ -88,6 +89,17 @@ export class AuthProviderEntryDBImpl implements AuthProviderEntryDB {
8889
return repo.findOne(id);
8990
}
9091

92+
async findByOrgSlug(slug: string): Promise<AuthProviderEntry | undefined> {
93+
const repo = await this.getAuthProviderRepo();
94+
const query = repo
95+
.createQueryBuilder("auth_provider")
96+
.leftJoin(DBTeam, "organization", "organization.id = auth_provider.organizationId")
97+
.where(`organization.slug = :slug`, { slug })
98+
.andWhere("auth_provider.status = :status", { status: "verified" })
99+
.andWhere("auth_provider.deleted != true");
100+
return query.getOne();
101+
}
102+
91103
async findByUserId(ownerId: string): Promise<AuthProviderEntry[]> {
92104
const repo = await this.getAuthProviderRepo();
93105
const query = repo

components/gitpod-protocol/src/gitpod-service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export interface GitpodServer extends JsonRpcServer<GitpodClient>, AdminServer,
9898
getConfiguration(): Promise<Configuration>;
9999
getToken(query: GitpodServer.GetTokenSearchOptions): Promise<Token | undefined>;
100100
getGitpodTokenScopes(tokenHash: string): Promise<string[]>;
101+
getSSOLoginID(slug: string): Promise<{ id: string } | undefined>;
101102
/**
102103
* @deprecated
103104
*/

components/server/src/auth/auth-provider-service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ export class AuthProviderService {
166166
return await this.authProviderDB.storeAuthProvider(authProvider as AuthProviderEntry, true);
167167
}
168168

169+
// get org auth provider by slug
170+
async getOrgAuthProviderBySlug(slug: string): Promise<AuthProviderEntry | undefined> {
171+
return await this.authProviderDB.findByOrgSlug(slug);
172+
}
173+
169174
protected initializeNewProvider(newEntry: AuthProviderEntry.NewEntry): AuthProviderEntry {
170175
const { host, type, clientId, clientSecret } = newEntry;
171176
let urls;

components/server/src/auth/rate-limiter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ const defaultFunctions: FunctionsConfig = {
239239
updateWorkspaceTimeoutSetting: { group: "default", points: 1 },
240240
getIDToken: { group: "default", points: 1 },
241241
reportErrorBoundary: { group: "default", points: 1 },
242+
getSSOLoginID: { group: "default", points: 1 },
242243
};
243244

244245
function getConfig(config: RateLimiterConfig): RateLimiterConfig {

components/server/src/workspace/gitpod-server-impl.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,24 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable {
609609
return result;
610610
}
611611

612+
// TODO: Make a response type for this method
613+
public async getSSOLoginID(ctx: TraceContext, slug: string): Promise<{ id: string } | undefined> {
614+
// Lookup auth provider by org slug
615+
if (!slug) {
616+
throw new ResponseError(ErrorCodes.BAD_REQUEST, "slug must be provided");
617+
}
618+
619+
// return id of auth provider as login id
620+
const provider = await this.authProviderService.getOrgAuthProviderBySlug(slug);
621+
if (!provider) {
622+
return;
623+
}
624+
625+
return {
626+
id: provider.id,
627+
};
628+
}
629+
612630
public async getConfiguration(ctx: TraceContext): Promise<Configuration> {
613631
return {
614632
garbageCollectionStartDate: this.config.workspaceGarbageCollection.startDate,

0 commit comments

Comments
 (0)