From: David Ostrovsky Date: Fri, 4 Jul 2014 21:28:21 +0000 (+0200) Subject: GitHub OAuth login for GitBlit X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fheads%2Fticket%2F138;p=gitblit.git GitHub OAuth login for GitBlit --- diff --git a/src/main/java/com/gitblit/Constants.java b/src/main/java/com/gitblit/Constants.java index 279d3c92..15c60482 100644 --- a/src/main/java/com/gitblit/Constants.java +++ b/src/main/java/com/gitblit/Constants.java @@ -548,7 +548,7 @@ public class Constants { } public static enum AuthenticationType { - PUBLIC_KEY, CREDENTIALS, COOKIE, CERTIFICATE, CONTAINER; + PUBLIC_KEY, CREDENTIALS, COOKIE, CERTIFICATE, CONTAINER, GITHUB_OAUTH; public boolean isStandard() { return ordinal() <= COOKIE.ordinal(); diff --git a/src/main/java/com/gitblit/auth/github/AuthenticatedHttpRequest.java b/src/main/java/com/gitblit/auth/github/AuthenticatedHttpRequest.java new file mode 100644 index 00000000..b2b0e86a --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/AuthenticatedHttpRequest.java @@ -0,0 +1,51 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import com.google.common.collect.Iterators; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +class AuthenticatedHttpRequest extends HttpServletRequestWrapper { + private Map headers = new HashMap<>(); + + AuthenticatedHttpRequest(HttpServletRequest request, + String key, String value) { + super(request); + headers.put(key, value); + } + + @Override + public Enumeration getHeaderNames() { + return Iterators.asEnumeration( + Iterators.concat(Iterators.forEnumeration(super.getHeaderNames()), + headers.keySet().iterator())); + } + + @Override + public String getHeader(String name) { + String headerValue = headers.get(name); + if (headerValue != null) { + return headerValue; + } else { + return super.getHeader(name); + } + } +} diff --git a/src/main/java/com/gitblit/auth/github/GitHubLogin.java b/src/main/java/com/gitblit/auth/github/GitHubLogin.java new file mode 100644 index 00000000..0776494d --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/GitHubLogin.java @@ -0,0 +1,100 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import com.google.inject.Inject; +import com.google.inject.servlet.SessionScoped; + +import org.apache.http.HttpStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@SessionScoped +class GitHubLogin { + private static final Logger log = LoggerFactory.getLogger(GitHubLogin.class); + + private final OAuthProtocol oauth; + private String token; + private String user; + + @Inject + GitHubLogin(final OAuthProtocol oauth) { + this.oauth = oauth; + } + + boolean isLoggedIn() { + return token != null && user != null; + } + + boolean login(HttpServletRequest request, HttpServletResponse response) + throws IOException { + if (isLoggedIn()) { + return true; + } + + log.debug("Login " + this); + + if (OAuthProtocol.isOAuthFinal(request)) { + String redirectUrl = oauth.getTargetUrl(request); + if (redirectUrl == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return false; + } + + log.debug("Login-Retrieve-User " + this); + retrieveUser(oauth.loginPhase2(request, response)); + if (isLoggedIn()) { + log.debug("Login-SUCCESS " + this); + response.sendRedirect(redirectUrl); + return true; + } else { + response.sendError(HttpStatus.SC_UNAUTHORIZED); + return false; + } + } else { + log.debug("Login-PHASE1 " + this); + oauth.loginPhase1(request, response); + return false; + } + } + + void logout() { + token = null; + user = null; + } + + boolean isLoginRequest(HttpServletRequest httpRequest) { + return oauth.isOAuthRequest(httpRequest); + } + + String getUsername() { + return user; + } + + @Override + public String toString() { + return "GitHubLogin [token=" + token + ", user=" + user + "]"; + } + + private void retrieveUser(String authToken) throws IOException { + this.token = authToken; + this.user = oauth.retrieveUser(authToken); + } +} diff --git a/src/main/java/com/gitblit/auth/github/GitHubOAuthConfig.java b/src/main/java/com/gitblit/auth/github/GitHubOAuthConfig.java new file mode 100644 index 00000000..1a2fb756 --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/GitHubOAuthConfig.java @@ -0,0 +1,78 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import java.net.MalformedURLException; +import java.net.URL; + +import com.gitblit.IStoredSettings; +import com.google.common.base.CharMatcher; +import com.google.inject.Inject; +import com.google.inject.Singleton; + +@Singleton +class GitHubOAuthConfig { + private static final String GITHUB_URL = "https://github.com"; + private static final String GITHUB_API_URL = "https://api.github.com"; + protected static final String CONF_SECTION = "github"; + private static final String GITHUB_OAUTH_AUTHORIZE = "/login/oauth/authorize"; + public static final String GITHUB_OAUTH_ACCESS_TOKEN = + "/login/oauth/access_token"; + private static final String GITHUB_GET_USER = "/user"; + //private static final String GITHUB_OAUTH_FINAL = "/oauth"; + static final String GITHUB_LOGIN = "/login"; + + private final String gitHubUrl; + private final String gitHubApiUrl; + final String gitHubUserUrl; + final String gitHubClientId; + final String gitHubClientSecret; + final String httpHeader; + final String gitHubOAuthUrl; + final String oAuthFinalRedirectUrl; + final String gitHubOAuthAccessTokenUrl; + final boolean autoLogin; + + @Inject + GitHubOAuthConfig(IStoredSettings settings) + throws MalformedURLException { + httpHeader = settings.getString("httpHeader", "GITHUB_USER"); + gitHubUrl = GITHUB_URL; + gitHubApiUrl = GITHUB_API_URL; + gitHubClientId = settings.getString("clientId", "4711"); + gitHubClientSecret = settings.getString("clientSecret", "4712"); + + gitHubOAuthUrl = getUrl(gitHubUrl, GITHUB_OAUTH_AUTHORIZE); + gitHubOAuthAccessTokenUrl = getUrl(gitHubUrl, GITHUB_OAUTH_ACCESS_TOKEN); + gitHubUserUrl = getUrl(gitHubApiUrl, GITHUB_GET_USER); + oAuthFinalRedirectUrl = settings.getString("canonicalWebUrl", + "http://locahost:8080"); + autoLogin = false; + } + + private static String trimTrailingSlash(String url) { + return CharMatcher.is('/').trimTrailingFrom(url); + } + + private String getUrl(String baseUrl, String path) + throws MalformedURLException { + if (baseUrl.indexOf("://") > 0) { + return new URL(new URL(baseUrl), path).toExternalForm(); + } else { + return baseUrl + trimTrailingSlash(baseUrl) + "/" + + CharMatcher.is('/').trimLeadingFrom(path); + } + } +} diff --git a/src/main/java/com/gitblit/auth/github/HttpGitHubOAuthModule.java b/src/main/java/com/gitblit/auth/github/HttpGitHubOAuthModule.java new file mode 100644 index 00000000..91332b22 --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/HttpGitHubOAuthModule.java @@ -0,0 +1,32 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import com.google.inject.servlet.ServletModule; + +import org.apache.http.client.HttpClient; + +/** Servlets and support related to GitHub OAuth authentication. */ +public class HttpGitHubOAuthModule extends ServletModule { + + @Override + protected void configureServlets() { + filter("/").through(OAuthWebFilter.class); + filter("/login").through(OAuthWebFilter.class); + filter("/oauth").through(OAuthWebFilter.class); + + bind(HttpClient.class).toProvider(PooledHttpClientProvider.class); + } +} diff --git a/src/main/java/com/gitblit/auth/github/OAuthProtocol.java b/src/main/java/com/gitblit/auth/github/OAuthProtocol.java new file mode 100644 index 00000000..8e6b2846 --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/OAuthProtocol.java @@ -0,0 +1,240 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import com.google.common.base.Charsets; +import com.google.common.base.Strings; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.inject.Inject; + +import org.apache.commons.codec.binary.Base64; +import org.apache.http.HttpResponse; +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.HttpClient; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URLEncoder; +import java.security.SecureRandom; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +class OAuthProtocol { + private static final String ME_SEPARATOR = ","; + private static final Logger log = LoggerFactory + .getLogger(OAuthProtocol.class); + + private final GitHubOAuthConfig config; + private final HttpClient http; + private final Gson gson; + private final String state; + + @Inject + OAuthProtocol(GitHubOAuthConfig config, HttpClient http, + Gson gson) { + this.config = config; + this.http = http; + this.gson = gson; + this.state = generateRandomState(); + } + + void loginPhase1(HttpServletRequest request, + HttpServletResponse response) throws IOException { + log.debug("Initiating GitHub Login for ClientId=" + config.gitHubClientId); + response.sendRedirect(String.format( + "%s?client_id=%s&redirect_uri=%s&state=%s%s", config.gitHubOAuthUrl, + config.gitHubClientId, getURLEncoded(config.oAuthFinalRedirectUrl), + me(), getURLEncoded(request.getRequestURI().toString()))); + } + + String loginPhase2(HttpServletRequest request, + HttpServletResponse response) throws IOException { + HttpPost post = new HttpPost(config.gitHubOAuthAccessTokenUrl); + post.setHeader("Accept", "application/json"); + List nvps = new ArrayList<>(3); + nvps.add(new BasicNameValuePair("client_id", config.gitHubClientId)); + nvps.add(new BasicNameValuePair("client_secret", + config.gitHubClientSecret)); + nvps.add(new BasicNameValuePair("code", request.getParameter("code"))); + post.setEntity(new UrlEncodedFormEntity(nvps)); + + try { + HttpResponse postResponse = http.execute(post); + if (postResponse.getStatusLine().getStatusCode() != + HttpURLConnection.HTTP_OK) { + log.error("POST " + config.gitHubOAuthAccessTokenUrl + + " request for access token failed with status " + + postResponse.getStatusLine()); + response.sendError(HttpURLConnection.HTTP_UNAUTHORIZED, + "Request for access token not authorised"); + EntityUtils.consume(postResponse.getEntity()); + return null; + } + + return getAccessToken(getAccessTokenJson(postResponse)); + } catch (IOException e) { + log.error("POST " + config.gitHubOAuthAccessTokenUrl + + " request for access token failed", e); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, + "Request for access token not authorised"); + return null; + } + } + + String retrieveUser(String authToken) throws IOException { + HttpGet get = new HttpGet(config.gitHubUserUrl); + get.setHeader("Authorization", String.format("token %s", authToken)); + try { + return getLogin(getUserJson(httpGetGitHubUserInfo(get))); + } catch (IOException e) { + log.error("GET {} with authToken {} request failed", + config.gitHubUserUrl, config.gitHubOAuthAccessTokenUrl, e); + return null; + } + } + + private InputStream httpGetGitHubUserInfo(HttpGet get) throws IOException, + ClientProtocolException { + HttpResponse resp = http.execute(get); + int statusCode = resp.getStatusLine().getStatusCode(); + if (statusCode == HttpServletResponse.SC_OK) { + return resp.getEntity().getContent(); + } else { + throw new IOException(String.format( + "Invalid HTTP status code %s returned from %s", statusCode, + get.getURI())); + } + } + + private String getAccessToken(JsonElement accessTokenJson) + throws IOException { + JsonElement accessTokenString = + accessTokenJson.getAsJsonObject().get("access_token"); + if (accessTokenString != null) { + return accessTokenString.getAsString(); + } else { + throw new IOException(String.format( + "Invalid JSON '%s': cannot find access_token field", + accessTokenJson)); + } + } + + private JsonObject getAccessTokenJson(HttpResponse postResponse) + throws UnsupportedEncodingException, IOException { + JsonElement accessTokenJson = + gson.fromJson(new InputStreamReader(postResponse.getEntity() + .getContent(), Charsets.UTF_8), JsonElement.class); + if (accessTokenJson.isJsonObject()) { + return accessTokenJson.getAsJsonObject(); + } else { + throw new IOException(String.format( + "Invalid JSON '%s': not a JSON Object")); + } + } + + boolean isOAuthRequest(HttpServletRequest httpRequest) { + return OAuthProtocol.isGerritLogin(httpRequest) + || OAuthProtocol.isOAuthFinal(httpRequest); + } + + String getTargetUrl(ServletRequest request) { + String requestState = state(request); + int meEnd = requestState.indexOf(ME_SEPARATOR); + if (meEnd >= 0 && requestState.subSequence(0, meEnd).equals(state)) { + return requestState.substring(meEnd + 1); + } else { + log.warn("Illegal request state '" + requestState + "' on OAuthProtocol " + + this); + return null; + } + } + + private String me() { + return state + ME_SEPARATOR; + } + + private JsonObject getUserJson(InputStream userContentStream) + throws IOException { + JsonElement userJson = + gson.fromJson(new InputStreamReader(userContentStream, + Charsets.UTF_8), JsonElement.class); + if (userJson.isJsonObject()) { + return userJson.getAsJsonObject(); + } else { + throw new IOException(String.format( + "Invalid JSON '%s': not a JSON Object", userJson)); + } + } + + static boolean isOAuthFinal(HttpServletRequest request) { + return Strings.emptyToNull(request.getParameter("code")) != null; + } + + static boolean isGerritLogin(HttpServletRequest request) { + return request.getRequestURI().indexOf( + GitHubOAuthConfig.GITHUB_LOGIN) >= 0; + } + + private static String getLogin(JsonElement userJson) throws IOException { + JsonElement userString = userJson.getAsJsonObject().get("login"); + if (userString != null) { + return userString.getAsString(); + } else { + throw new IOException(String.format( + "Invalid JSON '%s': cannot find login field", userJson)); + } + } + + private static String generateRandomState() { + byte[] randomState = new byte[32]; + new SecureRandom().nextBytes(randomState); + return Base64.encodeBase64URLSafeString(randomState); + } + + private static String getURLEncoded(String url) { + try { + return URLEncoder.encode(url, Charsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + // UTF-8 is hardcoded, cannot fail + return null; + } + } + + private static String state(ServletRequest request) { + return Strings.nullToEmpty(request.getParameter("state")); + } + + @Override + public String toString() { + return "OAuthProtocol/" + state; + } +} diff --git a/src/main/java/com/gitblit/auth/github/OAuthWebFilter.java b/src/main/java/com/gitblit/auth/github/OAuthWebFilter.java new file mode 100644 index 00000000..905bdc08 --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/OAuthWebFilter.java @@ -0,0 +1,96 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.gitblit.auth.github; + + +import com.gitblit.manager.IAuthenticationManager; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@Singleton +class OAuthWebFilter implements Filter { + private static final Logger log = LoggerFactory + .getLogger(OAuthWebFilter.class); + + private final GitHubOAuthConfig config; + private final Provider loginProvider; + private final IAuthenticationManager authenticationManager; + + @Inject + OAuthWebFilter(GitHubOAuthConfig config, + Provider loginProvider, + IAuthenticationManager authenticationManager) { + this.config = config; + this.loginProvider = loginProvider; + this.authenticationManager = authenticationManager; + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + HttpSession httpSession = ((HttpServletRequest) request).getSession(false); + // TODO(davido): FixMe: How to do that on gitblit? + //if (authenticationManager.isIdentifiedUser()) { + if (false) { + if (httpSession != null) { + httpSession.invalidate(); + } + chain.doFilter(request, response); + return; + } + + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + log.debug("OAuthWebFilter({})", httpRequest.getRequestURL()); + + GitHubLogin ghLogin = loginProvider.get(); + + if (ghLogin.isLoginRequest(httpRequest) && !ghLogin.isLoggedIn()) { + ghLogin.login(httpRequest, httpResponse); + } else if (config.autoLogin && !ghLogin.isLoggedIn()) { + httpResponse.sendRedirect("/login"); + } else { + if (ghLogin.isLoggedIn()) { + httpRequest = + new AuthenticatedHttpRequest(httpRequest, config.httpHeader, + ghLogin.getUsername()); + } + chain.doFilter(httpRequest, response); + } + } + + @Override + public void destroy() { + } +} diff --git a/src/main/java/com/gitblit/auth/github/PooledHttpClientProvider.java b/src/main/java/com/gitblit/auth/github/PooledHttpClientProvider.java new file mode 100644 index 00000000..3eadfb5e --- /dev/null +++ b/src/main/java/com/gitblit/auth/github/PooledHttpClientProvider.java @@ -0,0 +1,36 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.gitblit.auth.github; + +import org.apache.http.client.HttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +import com.google.inject.Provider; +import com.google.inject.Singleton; + +@Singleton +class PooledHttpClientProvider implements Provider { + + @Override + public HttpClient get() { + // TODO(davido): handle proxy + // TODO(davido): externalize MaxConnPerRoute && MaxConnTotal values + return HttpClientBuilder + .create() + .setMaxConnPerRoute(100) + .setMaxConnTotal(1024) + .build(); + } +} diff --git a/src/main/java/com/gitblit/guice/WebModule.java b/src/main/java/com/gitblit/guice/WebModule.java index 5b569182..35ef5725 100644 --- a/src/main/java/com/gitblit/guice/WebModule.java +++ b/src/main/java/com/gitblit/guice/WebModule.java @@ -19,6 +19,7 @@ import java.util.HashMap; import java.util.Map; import com.gitblit.Constants; +import com.gitblit.auth.github.HttpGitHubOAuthModule; import com.gitblit.servlet.BranchGraphServlet; import com.gitblit.servlet.DownloadZipFilter; import com.gitblit.servlet.DownloadZipServlet; @@ -92,6 +93,11 @@ public class WebModule extends ServletModule { params.put(GitblitWicketFilter.FILTER_MAPPING_PARAM, ALL); params.put(GitblitWicketFilter.IGNORE_PATHS_PARAM, toIgnore); filter(ALL).through(GitblitWicketFilter.class, params); + + //if (AUTH_METHOD == GITHUB_OAUTH) { + if (true) { + install(new HttpGitHubOAuthModule()); + } } private String fuzzy(String path) { diff --git a/src/site/setup_authentication.mkd b/src/site/setup_authentication.mkd index 02d1be70..10c41ec3 100644 --- a/src/site/setup_authentication.mkd +++ b/src/site/setup_authentication.mkd @@ -4,6 +4,7 @@ By default, Gitblit stores and authenticates all users against `users.conf`. Ho Gitblit supports additional authentication mechanisms aside from it's internal one. +* GitHub OAuth * LDAP authentication * Windows authentication * PAM authentication @@ -12,6 +13,43 @@ Gitblit supports additional authentication mechanisms aside from it's internal o * Salesforce.com authentication * Servlet container authentication +### GitHub OAuth +*SINCE 1.7.0 + +OAuth2 is a protocol that lets external apps request authorization to private +details in a user’s GitHub account without getting their password. This is +preferred over Basic Authentication because tokens can be limited to specific +types of data, and can be revoked by users at any time. ++ +Site owners have to register their application before getting started. For +more information see +https://github.com/settings/applications/new[github-register-application]. +A registered OAuth application is assigned a unique `Client ID` and `Client +Secret`. The `Client Secret` should never be shared. + +[[github.url]]github.url:: + +GitHub URL. + +Default is `https://github.com`. + +[[github.apiUrl]]github.apiUrl:: + +GitHub API URL. + +Default is `https://api.github.com`. + +[[github.clientId]]github.clientId:: + +The `Client ID`, that was received from GitHub when the application was +registered. Required. + +[[github.clientSecret]]github.clientSecret:: + +The `Client Secret`, that was received from GitHub when the application was +registered. Required. + + ### LDAP Authentication *SINCE 1.0.0*