Task #2852 ยป tdf-oauth.patch
src/main/java/com/googlesource/gerrit/plugins/oauth/HttpModule.java | ||
---|---|---|
78 | 78 |
.to(GitLabOAuthService.class); |
79 | 79 |
} |
80 | 80 | |
81 |
cfg = cfgFactory.getFromGerritConfig(pluginName + LemonLDAPOAuthService.CONFIG_SUFFIX); |
|
82 |
if (cfg.getString(InitOAuth.CLIENT_ID) != null) { |
|
83 |
bind(OAuthServiceProvider.class) |
|
84 |
.annotatedWith(Exports.named(LemonLDAPOAuthService.CONFIG_SUFFIX)) |
|
85 |
.to(LemonLDAPOAuthService.class); |
|
86 |
} |
|
87 | ||
81 | 88 |
cfg = cfgFactory.getFromGerritConfig(pluginName + DexOAuthService.CONFIG_SUFFIX); |
82 | 89 |
if (cfg.getString(InitOAuth.CLIENT_ID) != null) { |
83 | 90 |
bind(OAuthServiceProvider.class) |
src/main/java/com/googlesource/gerrit/plugins/oauth/InitOAuth.java | ||
---|---|---|
39 | 39 |
private final Section casOAuthProviderSection; |
40 | 40 |
private final Section facebookOAuthProviderSection; |
41 | 41 |
private final Section gitlabOAuthProviderSection; |
42 |
private final Section lemonldapOAuthProviderSection; |
|
42 | 43 |
private final Section dexOAuthProviderSection; |
43 | 44 |
private final Section keycloakOAuthProviderSection; |
44 | 45 |
private final Section office365OAuthProviderSection; |
... | ... | |
59 | 60 |
sections.get(PLUGIN_SECTION, pluginName + FacebookOAuthService.CONFIG_SUFFIX); |
60 | 61 |
this.gitlabOAuthProviderSection = |
61 | 62 |
sections.get(PLUGIN_SECTION, pluginName + GitLabOAuthService.CONFIG_SUFFIX); |
63 |
this.lemonldapOAuthProviderSection = |
|
64 |
sections.get(PLUGIN_SECTION, pluginName + LemonLDAPOAuthService.CONFIG_SUFFIX); |
|
62 | 65 |
this.dexOAuthProviderSection = |
63 | 66 |
sections.get(PLUGIN_SECTION, pluginName + DexOAuthService.CONFIG_SUFFIX); |
64 | 67 |
this.keycloakOAuthProviderSection = |
... | ... | |
115 | 118 |
configureOAuth(gitlabOAuthProviderSection); |
116 | 119 |
} |
117 | 120 | |
121 |
boolean configureLemonLDAPOAuthProvider = |
|
122 |
ui.yesno(true, "Use LemonLDAP OAuth provider for Gerrit login ?"); |
|
123 |
if (configureLemonLDAPOAuthProvider) { |
|
124 |
lemonldapOAuthProviderSection.string("LemonLDAP Root URL", ROOT_URL, null); |
|
125 |
configureOAuth(lemonldapOAuthProviderSection); |
|
126 |
} |
|
127 | ||
118 | 128 |
boolean configureDexOAuthProvider = ui.yesno(true, "Use Dex OAuth provider for Gerrit login ?"); |
119 | 129 |
if (configureDexOAuthProvider) { |
120 | 130 |
dexOAuthProviderSection.string("Dex Root URL", ROOT_URL, null); |
src/main/java/com/googlesource/gerrit/plugins/oauth/LemonLDAPApi.java | ||
---|---|---|
1 |
// Copyright (C) 2017 The Android Open Source Project |
|
2 |
// |
|
3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 |
// you may not use this file except in compliance with the License. |
|
5 |
// You may obtain a copy of the License at |
|
6 |
// |
|
7 |
// http://www.apache.org/licenses/LICENSE-2.0 |
|
8 |
// |
|
9 |
// Unless required by applicable law or agreed to in writing, software |
|
10 |
// distributed under the License is distributed on an "AS IS" BASIS, |
|
11 |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 |
// See the License for the specific language governing permissions and |
|
13 |
// limitations under the License. |
|
14 | ||
15 |
package com.googlesource.gerrit.plugins.oauth; |
|
16 | ||
17 |
import org.scribe.builder.api.DefaultApi20; |
|
18 |
import org.scribe.extractors.AccessTokenExtractor; |
|
19 |
import org.scribe.model.OAuthConfig; |
|
20 |
import org.scribe.model.Verb; |
|
21 |
import org.scribe.oauth.OAuthService; |
|
22 | ||
23 |
public class LemonLDAPApi extends DefaultApi20 { |
|
24 |
private static final String AUTHORIZE_URL = |
|
25 |
"%s/oauth2/authorize?client_id=%s&response_type=code&scope=openid+email+profile&redirect_uri=%s"; |
|
26 | ||
27 |
private final String rootUrl; |
|
28 | ||
29 |
public LemonLDAPApi(String rootUrl) { |
|
30 |
this.rootUrl = rootUrl; |
|
31 |
} |
|
32 | ||
33 |
@Override |
|
34 |
public String getAuthorizationUrl(OAuthConfig config) { |
|
35 |
return String.format(AUTHORIZE_URL, rootUrl, config.getApiKey(), config.getCallback()); |
|
36 |
} |
|
37 | ||
38 |
@Override |
|
39 |
public String getAccessTokenEndpoint() { |
|
40 |
return String.format("%s/oauth2/token", rootUrl); |
|
41 |
} |
|
42 | ||
43 |
@Override |
|
44 |
public Verb getAccessTokenVerb() { |
|
45 |
return Verb.POST; |
|
46 |
} |
|
47 | ||
48 |
@Override |
|
49 |
public OAuthService createService(OAuthConfig config) { |
|
50 |
return new OAuth20ServiceImpl(this, config); |
|
51 |
} |
|
52 | ||
53 |
@Override |
|
54 |
public AccessTokenExtractor getAccessTokenExtractor() { |
|
55 |
return OAuth2AccessTokenJsonExtractor.instance(); |
|
56 |
} |
|
57 |
} |
src/main/java/com/googlesource/gerrit/plugins/oauth/LemonLDAPOAuthService.java | ||
---|---|---|
1 |
// Copyright (C) 2017 The Android Open Source Project |
|
2 |
// |
|
3 |
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
4 |
// you may not use this file except in compliance with the License. |
|
5 |
// You may obtain a copy of the License at |
|
6 |
// |
|
7 |
// http://www.apache.org/licenses/LICENSE-2.0 |
|
8 |
// |
|
9 |
// Unless required by applicable law or agreed to in writing, software |
|
10 |
// distributed under the License is distributed on an "AS IS" BASIS, |
|
11 |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
12 |
// See the License for the specific language governing permissions and |
|
13 |
// limitations under the License. |
|
14 | ||
15 |
package com.googlesource.gerrit.plugins.oauth; |
|
16 | ||
17 |
import static com.google.gerrit.server.OutputFormat.JSON; |
|
18 |
import static javax.servlet.http.HttpServletResponse.SC_OK; |
|
19 |
import static org.slf4j.LoggerFactory.getLogger; |
|
20 | ||
21 |
import com.google.common.base.CharMatcher; |
|
22 |
import com.google.gerrit.extensions.annotations.PluginName; |
|
23 |
import com.google.gerrit.extensions.auth.oauth.OAuthServiceProvider; |
|
24 |
import com.google.gerrit.extensions.auth.oauth.OAuthToken; |
|
25 |
import com.google.gerrit.extensions.auth.oauth.OAuthUserInfo; |
|
26 |
import com.google.gerrit.extensions.auth.oauth.OAuthVerifier; |
|
27 |
import com.google.gerrit.server.config.CanonicalWebUrl; |
|
28 |
import com.google.gerrit.server.config.PluginConfig; |
|
29 |
import com.google.gerrit.server.config.PluginConfigFactory; |
|
30 |
import com.google.gson.JsonElement; |
|
31 |
import com.google.gson.JsonObject; |
|
32 |
import com.google.inject.Inject; |
|
33 |
import com.google.inject.Provider; |
|
34 |
import com.google.inject.Singleton; |
|
35 |
import java.io.IOException; |
|
36 |
import org.scribe.builder.ServiceBuilder; |
|
37 |
import org.scribe.model.OAuthRequest; |
|
38 |
import org.scribe.model.Response; |
|
39 |
import org.scribe.model.Token; |
|
40 |
import org.scribe.model.Verb; |
|
41 |
import org.scribe.model.Verifier; |
|
42 |
import org.scribe.oauth.OAuthService; |
|
43 |
import org.slf4j.Logger; |
|
44 | ||
45 |
@Singleton |
|
46 |
public class LemonLDAPOAuthService implements OAuthServiceProvider { |
|
47 |
private static final Logger log = getLogger(LemonLDAPOAuthService.class); |
|
48 |
static final String CONFIG_SUFFIX = "-lemonldap-oauth"; |
|
49 |
private static final String PROTECTED_RESOURCE_URL = "%s/oauth2/userinfo"; |
|
50 |
private static final String LEMONLDAP_PROVIDER_PREFIX = "tdf-oauth:"; |
|
51 |
private final OAuthService service; |
|
52 |
private final String rootUrl; |
|
53 | ||
54 |
@Inject |
|
55 |
LemonLDAPOAuthService( |
|
56 |
PluginConfigFactory cfgFactory, |
|
57 |
@PluginName String pluginName, |
|
58 |
@CanonicalWebUrl Provider<String> urlProvider) { |
|
59 |
PluginConfig cfg = cfgFactory.getFromGerritConfig(pluginName + CONFIG_SUFFIX); |
|
60 |
String canonicalWebUrl = CharMatcher.is('/').trimTrailingFrom(urlProvider.get()) + "/"; |
|
61 |
rootUrl = cfg.getString(InitOAuth.ROOT_URL); |
|
62 |
service = |
|
63 |
new ServiceBuilder() |
|
64 |
.provider(new LemonLDAPApi(rootUrl)) |
|
65 |
.apiKey(cfg.getString(InitOAuth.CLIENT_ID)) |
|
66 |
.apiSecret(cfg.getString(InitOAuth.CLIENT_SECRET)) |
|
67 |
.callback(canonicalWebUrl + "oauth") |
|
68 |
.build(); |
|
69 |
} |
|
70 | ||
71 |
@Override |
|
72 |
public OAuthUserInfo getUserInfo(OAuthToken token) throws IOException { |
|
73 |
final String protectedResourceUrl = String.format(PROTECTED_RESOURCE_URL, rootUrl); |
|
74 |
OAuthRequest request = new OAuthRequest(Verb.GET, protectedResourceUrl); |
|
75 |
Token t = new Token(token.getToken(), token.getSecret(), token.getRaw()); |
|
76 |
service.signRequest(t, request); |
|
77 | ||
78 |
Response response = request.send(); |
|
79 |
if (response.getCode() != SC_OK) { |
|
80 |
throw new IOException( |
|
81 |
String.format( |
|
82 |
"Status %s (%s) for request %s", |
|
83 |
response.getCode(), response.getBody(), request.getUrl())); |
|
84 |
} |
|
85 |
JsonElement userJson = JSON.newGson().fromJson(response.getBody(), JsonElement.class); |
|
86 |
if (log.isDebugEnabled()) { |
|
87 |
log.debug("User info response: {}", response.getBody()); |
|
88 |
} |
|
89 |
JsonObject jsonObject = userJson.getAsJsonObject(); |
|
90 |
if (jsonObject == null || jsonObject.isJsonNull()) { |
|
91 |
throw new IOException("Response doesn't contain 'user' field" + jsonObject); |
|
92 |
} |
|
93 |
JsonElement id = jsonObject.get("sub"); |
|
94 |
JsonElement username = jsonObject.get("username"); |
|
95 |
JsonElement email = jsonObject.get("email"); |
|
96 |
JsonElement name = jsonObject.get("name"); |
|
97 |
return new OAuthUserInfo( |
|
98 |
LEMONLDAP_PROVIDER_PREFIX + id.getAsString(), |
|
99 |
username == null || username.isJsonNull() ? null : username.getAsString(), |
|
100 |
email == null || email.isJsonNull() ? null : email.getAsString(), |
|
101 |
name == null || name.isJsonNull() ? null : name.getAsString(), |
|
102 |
null); |
|
103 |
} |
|
104 | ||
105 |
@Override |
|
106 |
public OAuthToken getAccessToken(OAuthVerifier rv) { |
|
107 |
Verifier vi = new Verifier(rv.getValue()); |
|
108 |
Token to = service.getAccessToken(null, vi); |
|
109 |
return new OAuthToken(to.getToken(), to.getSecret(), to.getRawResponse()); |
|
110 |
} |
|
111 | ||
112 |
@Override |
|
113 |
public String getAuthorizationUrl() { |
|
114 |
return service.getAuthorizationUrl(null); |
|
115 |
} |
|
116 | ||
117 |
@Override |
|
118 |
public String getVersion() { |
|
119 |
return service.getVersion(); |
|
120 |
} |
|
121 | ||
122 |
@Override |
|
123 |
public String getName() { |
|
124 |
return "The Document Foundation OAuth2"; |
|
125 |
} |
|
126 |
} |