-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathgitlab-auth-provider.ts
113 lines (100 loc) · 4.17 KB
/
gitlab-auth-provider.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* Copyright (c) 2020 Gitpod GmbH. All rights reserved.
* Licensed under the GNU Affero General Public License (AGPL).
* See License-AGPL.txt in the project root for license information.
*/
import * as express from "express";
import { injectable } from 'inversify';
import { log } from '@gitpod/gitpod-protocol/lib/util/logging';
import { AuthProviderInfo } from '@gitpod/gitpod-protocol';
import { GitLabScope } from "./scopes";
import { UnconfirmedUserException } from "../auth/errors";
import { GitLab } from "./api";
import { GenericAuthProvider } from "../auth/generic-auth-provider";
import { AuthUserSetup } from "../auth/auth-provider";
import { oauthUrls } from "./gitlab-urls";
@injectable()
export class GitLabAuthProvider extends GenericAuthProvider {
get info(): AuthProviderInfo {
return {
...this.defaultInfo(),
scopes: GitLabScope.All,
requirements: {
default: GitLabScope.Requirements.DEFAULT,
publicRepo: GitLabScope.Requirements.REPO,
privateRepo: GitLabScope.Requirements.REPO,
},
}
}
/**
* Augmented OAuthConfig for GitLab
*/
protected get oauthConfig() {
const oauth = this.config.oauth!;
const defaultUrls = oauthUrls(this.config.host);
const scopeSeparator = " ";
return <typeof oauth>{
...oauth,
authorizationUrl: oauth.authorizationUrl || defaultUrls.authorizationUrl,
tokenUrl: oauth.tokenUrl || defaultUrls.tokenUrl,
settingsUrl: oauth.settingsUrl || defaultUrls.settingsUrl,
scope: GitLabScope.All.join(scopeSeparator),
scopeSeparator
};
}
authorize(req: express.Request, res: express.Response, next: express.NextFunction, scope?: string[]): void {
super.authorize(req, res, next, scope ? scope : GitLabScope.Requirements.DEFAULT);
}
protected get baseURL() {
return `https://${this.config.host}`;
}
protected readAuthUserSetup = async (accessToken: string, tokenResponse: object) => {
const api = GitLab.create({
oauthToken: accessToken,
host: this.baseURL
});
const getCurrentUser = async () => {
const response = await api.Users.current();
return response as unknown as GitLab.User;
}
const unconfirmedUserMessage = "Please confirm your GitLab account and try again.";
try {
const result = await getCurrentUser();
if (result) {
if (!result.confirmed_at) {
throw UnconfirmedUserException.create(unconfirmedUserMessage, result);
}
}
const { id, username, avatar_url, name, email } = result;
return <AuthUserSetup>{
authUser: {
authId: String(id),
authName: username,
avatarUrl: avatar_url,
name,
primaryEmail: email
},
currentScopes: this.readScopesFromVerifyParams(tokenResponse)
}
} catch (error) {
if (error && typeof error.description === "string" && error.description.includes("403 Forbidden")) {
// If GitLab is configured to disallow OAuth-token based API access for unconfirmed users, we need to reject this attempt
// 403 Forbidden - You (@...) must accept the Terms of Service in order to perform this action. Please access GitLab from a web browser to accept these terms.
throw UnconfirmedUserException.create(error.description, error);
} else {
log.error(`(${this.strategyName}) Reading current user info failed`, error, { accessToken, error });
throw error;
}
}
}
protected readScopesFromVerifyParams(params: any) {
if (params && typeof params.scope === 'string') {
return this.normalizeScopes(params.scope.split(' '));
}
return [];
}
protected normalizeScopes(scopes: string[]) {
const set = new Set(scopes);
return Array.from(set).sort();
}
}