mirror of
https://github.com/theonedev/onedev.git
synced 2025-12-08 18:26:30 +00:00
Update nimus oauth sdk library
This commit is contained in:
parent
066fbc9209
commit
a07510f2b0
8
pom.xml
8
pom.xml
@ -257,7 +257,7 @@
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>oauth2-oidc-sdk</artifactId>
|
||||
<version>3.4.1</version>
|
||||
<version>9.35</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
@ -396,7 +396,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||
<version>${lucene.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -588,8 +588,8 @@
|
||||
</repository>
|
||||
</repositories>
|
||||
<properties>
|
||||
<commons.version>2.2.3</commons.version>
|
||||
<agent.version>1.3.16</agent.version>
|
||||
<commons.version>2.2.4</commons.version>
|
||||
<agent.version>1.3.17</agent.version>
|
||||
<slf4j.version>1.7.30</slf4j.version>
|
||||
<logback.version>1.2.9</logback.version>
|
||||
<antlr.version>4.7.2</antlr.version>
|
||||
|
||||
@ -118,7 +118,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
|
||||
@ -12,12 +12,6 @@
|
||||
<dependency>
|
||||
<groupId>com.nimbusds</groupId>
|
||||
<artifactId>oauth2-oidc-sdk</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
|
||||
@ -1,566 +0,0 @@
|
||||
package com.nimbusds.oauth2.sdk.http;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.http.entity.ContentType;
|
||||
|
||||
import net.jcip.annotations.ThreadSafe;
|
||||
|
||||
import net.minidev.json.JSONObject;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.ParseException;
|
||||
import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
|
||||
import com.nimbusds.oauth2.sdk.util.URLUtils;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP request with support for the parameters required to construct an
|
||||
* {@link com.nimbusds.oauth2.sdk.Request OAuth 2.0 request message}.
|
||||
*
|
||||
* <p>Supported HTTP methods:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link Method#GET HTTP GET}
|
||||
* <li>{@link Method#POST HTTP POST}
|
||||
* <li>{@link Method#POST HTTP PUT}
|
||||
* <li>{@link Method#POST HTTP DELETE}
|
||||
* </ul>
|
||||
*
|
||||
* <p>Supported request headers:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Content-Type
|
||||
* <li>Authorization
|
||||
* </ul>
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class HTTPRequest extends HTTPMessage {
|
||||
|
||||
|
||||
/**
|
||||
* Enumeration of the HTTP methods used in OAuth 2.0 requests.
|
||||
*/
|
||||
public static enum Method {
|
||||
|
||||
/**
|
||||
* HTTP GET.
|
||||
*/
|
||||
GET,
|
||||
|
||||
|
||||
/**
|
||||
* HTTP POST.
|
||||
*/
|
||||
POST,
|
||||
|
||||
|
||||
/**
|
||||
* HTTP PUT.
|
||||
*/
|
||||
PUT,
|
||||
|
||||
|
||||
/**
|
||||
* HTTP DELETE.
|
||||
*/
|
||||
DELETE
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The request method.
|
||||
*/
|
||||
private final Method method;
|
||||
|
||||
|
||||
/**
|
||||
* The request URL.
|
||||
*/
|
||||
private final URL url;
|
||||
|
||||
|
||||
/**
|
||||
* Specifies an {@code Authorization} header value.
|
||||
*/
|
||||
private String authorization = null;
|
||||
|
||||
|
||||
/**
|
||||
* The query string / post body.
|
||||
*/
|
||||
private String query = null;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new minimally specified HTTP request.
|
||||
*
|
||||
* @param method The HTTP request method. Must not be {@code null}.
|
||||
* @param url The HTTP request URL. Must not be {@code null}.
|
||||
*/
|
||||
public HTTPRequest(final Method method, final URL url) {
|
||||
|
||||
if (method == null)
|
||||
throw new IllegalArgumentException("The HTTP method must not be null");
|
||||
|
||||
this.method = method;
|
||||
|
||||
|
||||
if (url == null)
|
||||
throw new IllegalArgumentException("The HTTP URL must not be null");
|
||||
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reconstructs the request URL string for the specified servlet
|
||||
* request. The host part is always the local IP address. The query
|
||||
* string and fragment is always omitted.
|
||||
*
|
||||
* @param request The servlet request. Must not be {@code null}.
|
||||
*
|
||||
* @return The reconstructed request URL string.
|
||||
*/
|
||||
private static String reconstructRequestURLString(final HttpServletRequest request) {
|
||||
|
||||
StringBuilder sb = new StringBuilder("http");
|
||||
|
||||
if (request.isSecure())
|
||||
sb.append('s');
|
||||
|
||||
sb.append("://");
|
||||
|
||||
String localAddress = request.getLocalAddr();
|
||||
|
||||
if (localAddress.contains(".")) {
|
||||
// IPv3 address
|
||||
sb.append(localAddress);
|
||||
} else if (localAddress.contains(":")) {
|
||||
// IPv6 address, see RFC 2732
|
||||
sb.append('[');
|
||||
sb.append(localAddress);
|
||||
sb.append(']');
|
||||
} else {
|
||||
// Don't know what to do
|
||||
}
|
||||
|
||||
if (! request.isSecure() && request.getLocalPort() != 80) {
|
||||
// HTTP plain at port other than 80
|
||||
sb.append(':');
|
||||
sb.append(request.getLocalPort());
|
||||
}
|
||||
|
||||
if (request.isSecure() && request.getLocalPort() != 443) {
|
||||
// HTTPS at port other than 443 (default TLS)
|
||||
sb.append(':');
|
||||
sb.append(request.getLocalPort());
|
||||
}
|
||||
|
||||
String path = request.getRequestURI();
|
||||
|
||||
if (path != null)
|
||||
sb.append(path);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new HTTP request from the specified HTTP servlet request.
|
||||
*
|
||||
* @param sr The servlet request. Must not be {@code null}.
|
||||
*
|
||||
* @throws IllegalArgumentException The the servlet request method is
|
||||
* not GET, POST, PUT or DELETE or the
|
||||
* content type header value couldn't
|
||||
* be parsed.
|
||||
* @throws IOException For a POST or PUT body that
|
||||
* couldn't be read due to an I/O
|
||||
* exception.
|
||||
*/
|
||||
public HTTPRequest(final HttpServletRequest sr)
|
||||
throws IOException {
|
||||
|
||||
method = HTTPRequest.Method.valueOf(sr.getMethod().toUpperCase());
|
||||
|
||||
String urlString = reconstructRequestURLString(sr);
|
||||
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
|
||||
throw new IllegalArgumentException("Invalid request URL: " + e.getMessage() + ": " + urlString, e);
|
||||
}
|
||||
|
||||
try {
|
||||
setContentType(sr.getContentType());
|
||||
|
||||
} catch (ParseException e) {
|
||||
|
||||
throw new IllegalArgumentException("Invalid Content-Type header value: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
setAuthorization(sr.getHeader("Authorization"));
|
||||
|
||||
if (method.equals(Method.GET) || method.equals(Method.DELETE)) {
|
||||
|
||||
setQuery(sr.getQueryString());
|
||||
|
||||
} else if (method.equals(Method.POST) || method.equals(Method.PUT)) {
|
||||
|
||||
// read body
|
||||
StringBuilder body = new StringBuilder(256);
|
||||
|
||||
BufferedReader reader = sr.getReader();
|
||||
|
||||
String line;
|
||||
|
||||
boolean firstLine = true;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
if (firstLine)
|
||||
firstLine = false;
|
||||
else
|
||||
body.append(System.getProperty("line.separator"));
|
||||
body.append(line);
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
setQuery(body.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request method.
|
||||
*
|
||||
* @return The request method.
|
||||
*/
|
||||
public Method getMethod() {
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request URL.
|
||||
*
|
||||
* @return The request URL.
|
||||
*/
|
||||
public URL getURL() {
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensures this HTTP request has the specified method.
|
||||
*
|
||||
* @param expectedMethod The expected method. Must not be {@code null}.
|
||||
*
|
||||
* @throws ParseException If the method doesn't match the expected.
|
||||
*/
|
||||
public void ensureMethod(final Method expectedMethod)
|
||||
throws ParseException {
|
||||
|
||||
if (method != expectedMethod)
|
||||
throw new ParseException("The HTTP request method must be " + expectedMethod);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@code Authorization} header value.
|
||||
*
|
||||
* @return The {@code Authorization} header value, {@code null} if not
|
||||
* specified.
|
||||
*/
|
||||
public String getAuthorization() {
|
||||
|
||||
return authorization;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the {@code Authorization} header value.
|
||||
*
|
||||
* @param authz The {@code Authorization} header value, {@code null} if
|
||||
* not specified.
|
||||
*/
|
||||
public void setAuthorization(final String authz) {
|
||||
|
||||
authorization = authz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the raw (undecoded) query string if the request is HTTP GET or
|
||||
* the entity body if the request is HTTP POST.
|
||||
*
|
||||
* <p>Note that the '?' character preceding the query string in GET
|
||||
* requests is not included in the returned string.
|
||||
*
|
||||
* <p>Example query string (line breaks for clarity):
|
||||
*
|
||||
* <pre>
|
||||
* response_type=code
|
||||
* &client_id=s6BhdRkqt3
|
||||
* &state=xyz
|
||||
* &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
|
||||
* </pre>
|
||||
*
|
||||
* @return For HTTP GET requests the URL query string, for HTTP POST
|
||||
* requests the body. {@code null} if not specified.
|
||||
*/
|
||||
public String getQuery() {
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the raw (undecoded) query string if the request is HTTP GET or
|
||||
* the entity body if the request is HTTP POST.
|
||||
*
|
||||
* <p>Note that the '?' character preceding the query string in GET
|
||||
* requests must not be included.
|
||||
*
|
||||
* <p>Example query string (line breaks for clarity):
|
||||
*
|
||||
* <pre>
|
||||
* response_type=code
|
||||
* &client_id=s6BhdRkqt3
|
||||
* &state=xyz
|
||||
* &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
|
||||
* </pre>
|
||||
*
|
||||
* @param query For HTTP GET requests the URL query string, for HTTP
|
||||
* POST requests the body. {@code null} if not specified.
|
||||
*/
|
||||
public void setQuery(final String query) {
|
||||
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensures this HTTP response has a specified query string or entity
|
||||
* body.
|
||||
*
|
||||
* @throws ParseException If the query string or entity body is missing
|
||||
* or empty.
|
||||
*/
|
||||
private void ensureQuery()
|
||||
throws ParseException {
|
||||
|
||||
if (query == null || query.trim().isEmpty())
|
||||
throw new ParseException("Missing or empty HTTP query string / entity body");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request query as a parameter map. The parameters are
|
||||
* decoded according to {@code application/x-www-form-urlencoded}.
|
||||
*
|
||||
* @return The request query parameters, decoded. If none the map will
|
||||
* be empty.
|
||||
*/
|
||||
public Map<String,String> getQueryParameters() {
|
||||
|
||||
return URLUtils.parseParameters(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request query or entity body as a JSON Object.
|
||||
*
|
||||
* @return The request query or entity body as a JSON object.
|
||||
*
|
||||
* @throws ParseException If the Content-Type header isn't
|
||||
* {@code application/json}, the request query
|
||||
* or entity body is {@code null}, empty or
|
||||
* couldn't be parsed to a valid JSON object.
|
||||
*/
|
||||
public JSONObject getQueryAsJSONObject()
|
||||
throws ParseException {
|
||||
|
||||
ensureContentType(CommonContentTypes.APPLICATION_JSON);
|
||||
|
||||
ensureQuery();
|
||||
|
||||
return JSONObjectUtils.parseJSONObject(query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an established HTTP URL connection for this HTTP request.
|
||||
*
|
||||
* @return The HTTP URL connection, with the request sent and ready to
|
||||
* read the response.
|
||||
*
|
||||
* @throws IOException If the HTTP request couldn't be made, due to a
|
||||
* network or other error.
|
||||
*/
|
||||
public HttpURLConnection toHttpURLConnection()
|
||||
throws IOException {
|
||||
|
||||
URL finalURL = url;
|
||||
|
||||
if (query != null && (method.equals(HTTPRequest.Method.GET) || method.equals(Method.DELETE))) {
|
||||
|
||||
// Append query string
|
||||
StringBuilder sb = new StringBuilder(url.toString());
|
||||
sb.append('?');
|
||||
sb.append(query);
|
||||
|
||||
try {
|
||||
finalURL = new URL(sb.toString());
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
|
||||
throw new IOException("Couldn't append query string: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection)finalURL.openConnection();
|
||||
|
||||
if (authorization != null)
|
||||
conn.setRequestProperty("Authorization", authorization);
|
||||
|
||||
conn.setRequestProperty("Accept", ContentType.APPLICATION_JSON.toString());
|
||||
|
||||
conn.setRequestMethod(method.name());
|
||||
|
||||
if (method.equals(HTTPRequest.Method.POST) || method.equals(Method.PUT)) {
|
||||
|
||||
conn.setDoOutput(true);
|
||||
|
||||
if (getContentType() != null)
|
||||
conn.setRequestProperty("Content-Type", getContentType().toString());
|
||||
|
||||
if (query != null) {
|
||||
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
|
||||
writer.write(query);
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends this HTTP request to the request URL and retrieves the
|
||||
* resulting HTTP response.
|
||||
*
|
||||
* @return The resulting HTTP response.
|
||||
*
|
||||
* @throws IOException If the HTTP request couldn't be made, due to a
|
||||
* network or other error.
|
||||
*/
|
||||
public HTTPResponse send()
|
||||
throws IOException {
|
||||
|
||||
HttpURLConnection conn = toHttpURLConnection();
|
||||
|
||||
int statusCode;
|
||||
|
||||
BufferedReader reader;
|
||||
|
||||
try {
|
||||
// Open a connection, then send method and headers
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
|
||||
// The next step is to get the status
|
||||
statusCode = conn.getResponseCode();
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
// HttpUrlConnection will throw an IOException if any
|
||||
// 4XX response is sent. If we request the status
|
||||
// again, this time the internal status will be
|
||||
// properly set, and we'll be able to retrieve it.
|
||||
statusCode = conn.getResponseCode();
|
||||
|
||||
if (statusCode == -1) {
|
||||
// Rethrow IO exception
|
||||
throw e;
|
||||
} else {
|
||||
// HTTP status code indicates the response got
|
||||
// through, read the content but using error
|
||||
// stream
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
||||
|
||||
try {
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
|
||||
body.append(line);
|
||||
body.append(System.getProperty("line.separator"));
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
} finally {
|
||||
conn.disconnect();
|
||||
}
|
||||
|
||||
|
||||
HTTPResponse response = new HTTPResponse(statusCode);
|
||||
|
||||
String location = conn.getHeaderField("Location");
|
||||
|
||||
if (location != null) {
|
||||
|
||||
try {
|
||||
response.setLocation(new URL(location));
|
||||
|
||||
} catch (MalformedURLException e) {
|
||||
|
||||
throw new IOException("Couldn't parse Location header: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
response.setContentType(conn.getContentType());
|
||||
|
||||
} catch (ParseException e) {
|
||||
|
||||
throw new IOException("Couldn't parse Content-Type header: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
||||
response.setCacheControl(conn.getHeaderField("Cache-Control"));
|
||||
|
||||
response.setPragma(conn.getHeaderField("Pragma"));
|
||||
|
||||
response.setWWWAuthenticate(conn.getHeaderField("WWW-Authenticate"));
|
||||
|
||||
String bodyContent = body.toString();
|
||||
|
||||
if (! bodyContent.isEmpty())
|
||||
response.setContent(bodyContent);
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@ -1,185 +0,0 @@
|
||||
package com.nimbusds.openid.connect.sdk;
|
||||
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import net.jcip.annotations.Immutable;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.nimbusds.oauth2.sdk.ErrorObject;
|
||||
import com.nimbusds.oauth2.sdk.ErrorResponse;
|
||||
import com.nimbusds.oauth2.sdk.ParseException;
|
||||
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
|
||||
import com.nimbusds.oauth2.sdk.token.BearerTokenError;
|
||||
|
||||
|
||||
/**
|
||||
* UserInfo error response.
|
||||
*
|
||||
* <p>Standard OAuth 2.0 Bearer Token errors:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link com.nimbusds.oauth2.sdk.token.BearerTokenError#MISSING_TOKEN}
|
||||
* <li>{@link com.nimbusds.oauth2.sdk.token.BearerTokenError#INVALID_REQUEST}
|
||||
* <li>{@link com.nimbusds.oauth2.sdk.token.BearerTokenError#INVALID_TOKEN}
|
||||
* <li>{@link com.nimbusds.oauth2.sdk.token.BearerTokenError#INSUFFICIENT_SCOPE}
|
||||
* </ul>
|
||||
*
|
||||
* <p>Example HTTP response:
|
||||
*
|
||||
* <pre>
|
||||
* HTTP/1.1 401 Unauthorized
|
||||
* WWW-Authenticate: Bearer realm="example.com",
|
||||
* error="invalid_token",
|
||||
* error_description="The access token expired"
|
||||
* </pre>
|
||||
*
|
||||
* <p>Related specifications:
|
||||
*
|
||||
* <ul>
|
||||
* <li>OpenID Connect Core 1.0, section 5.3.3.
|
||||
* <li>OAuth 2.0 Bearer Token Usage (RFC 6750), section 3.1.
|
||||
* </ul>
|
||||
*/
|
||||
@Immutable
|
||||
public class UserInfoErrorResponse
|
||||
extends UserInfoResponse
|
||||
implements ErrorResponse {
|
||||
|
||||
|
||||
/**
|
||||
* Gets the standard errors for a UserInfo error response.
|
||||
*
|
||||
* @return The standard errors, as a read-only set.
|
||||
*/
|
||||
public static Set<BearerTokenError> getStandardErrors() {
|
||||
|
||||
Set<BearerTokenError> stdErrors = new HashSet<>();
|
||||
stdErrors.add(BearerTokenError.MISSING_TOKEN);
|
||||
stdErrors.add(BearerTokenError.INVALID_REQUEST);
|
||||
stdErrors.add(BearerTokenError.INVALID_TOKEN);
|
||||
stdErrors.add(BearerTokenError.INSUFFICIENT_SCOPE);
|
||||
|
||||
return Collections.unmodifiableSet(stdErrors);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The underlying bearer token error.
|
||||
*/
|
||||
private final BearerTokenError error;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new UserInfo error response. No OAuth 2.0 bearer token
|
||||
* error is specified.
|
||||
*/
|
||||
private UserInfoErrorResponse() {
|
||||
|
||||
error = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new UserInfo error response.
|
||||
*
|
||||
* @param error The OAuth 2.0 bearer token error. Should match one of
|
||||
* the {@link #getStandardErrors standard errors} for a
|
||||
* UserInfo error response. Must not be {@code null}.
|
||||
*/
|
||||
public UserInfoErrorResponse(final BearerTokenError error) {
|
||||
|
||||
if (error == null)
|
||||
throw new IllegalArgumentException("The error must not be null");
|
||||
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ErrorObject getErrorObject() {
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the HTTP response for this UserInfo error response.
|
||||
*
|
||||
* <p>Example HTTP response:
|
||||
*
|
||||
* <pre>
|
||||
* HTTP/1.1 401 Unauthorized
|
||||
* WWW-Authenticate: Bearer realm="example.com",
|
||||
* error="invalid_token",
|
||||
* error_description="The access token expired"
|
||||
* </pre>
|
||||
*
|
||||
* @return The HTTP response matching this UserInfo error response.
|
||||
*/
|
||||
@Override
|
||||
public HTTPResponse toHTTPResponse() {
|
||||
|
||||
HTTPResponse httpResponse;
|
||||
|
||||
if (error.getHTTPStatusCode() > 0)
|
||||
httpResponse = new HTTPResponse(error.getHTTPStatusCode());
|
||||
else
|
||||
httpResponse = new HTTPResponse(HTTPResponse.SC_BAD_REQUEST);
|
||||
|
||||
// Add the WWW-Authenticate header
|
||||
if (error != null)
|
||||
httpResponse.setWWWAuthenticate(error.toWWWAuthenticateHeader());
|
||||
|
||||
return httpResponse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a UserInfo error response from the specified HTTP response
|
||||
* {@code WWW-Authenticate} header.
|
||||
*
|
||||
* @param wwwAuth The {@code WWW-Authenticate} header value to parse.
|
||||
* Must not be {@code null}.
|
||||
*
|
||||
* @throws ParseException If the {@code WWW-Authenticate} header value
|
||||
* couldn't be parsed to a UserInfo error
|
||||
* response.
|
||||
*/
|
||||
public static UserInfoErrorResponse parse(final String wwwAuth)
|
||||
throws ParseException {
|
||||
|
||||
BearerTokenError error = BearerTokenError.parse(wwwAuth);
|
||||
|
||||
return new UserInfoErrorResponse(error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a UserInfo error response from the specified HTTP response.
|
||||
*
|
||||
* <p>Note: The HTTP status code is not checked for matching the error
|
||||
* code semantics.
|
||||
*
|
||||
* @param httpResponse The HTTP response to parse. Its status code must
|
||||
* not be 200 (OK). Must not be {@code null}.
|
||||
*
|
||||
* @throws ParseException If the HTTP response couldn't be parsed to a
|
||||
* UserInfo error response.
|
||||
*/
|
||||
public static UserInfoErrorResponse parse(final HTTPResponse httpResponse)
|
||||
throws ParseException {
|
||||
|
||||
httpResponse.ensureStatusCodeNotOK();
|
||||
|
||||
String wwwAuth = httpResponse.getWWWAuthenticate();
|
||||
|
||||
if (StringUtils.isNotBlank(wwwAuth))
|
||||
return parse(wwwAuth);
|
||||
|
||||
return new UserInfoErrorResponse();
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ import com.nimbusds.oauth2.sdk.ParseException;
|
||||
import com.nimbusds.oauth2.sdk.SerializeException;
|
||||
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
|
||||
import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
|
||||
import com.nimbusds.openid.connect.sdk.OIDCAccessTokenResponse;
|
||||
import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
|
||||
import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
|
||||
import com.nimbusds.openid.connect.sdk.UserInfoRequest;
|
||||
|
||||
@ -58,8 +58,8 @@ public class GitHubConnector extends OpenIdConnector {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SsoAuthenticated processTokenResponse(OIDCAccessTokenResponse tokenSuccessResponse) {
|
||||
BearerAccessToken accessToken = (BearerAccessToken) tokenSuccessResponse.getAccessToken();
|
||||
protected SsoAuthenticated processTokenResponse(OIDCTokenResponse tokenResponse) {
|
||||
BearerAccessToken accessToken = (BearerAccessToken) tokenResponse.getTokens().getBearerAccessToken();
|
||||
|
||||
try {
|
||||
UserInfoRequest userInfoRequest = new UserInfoRequest(
|
||||
|
||||
@ -20,8 +20,9 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.nimbusds.common.contenttype.ContentType;
|
||||
import com.nimbusds.jwt.JWT;
|
||||
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
|
||||
import com.nimbusds.jwt.JWTClaimsSet;
|
||||
import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
|
||||
import com.nimbusds.oauth2.sdk.AuthorizationGrant;
|
||||
import com.nimbusds.oauth2.sdk.ErrorObject;
|
||||
@ -29,11 +30,12 @@ import com.nimbusds.oauth2.sdk.ParseException;
|
||||
import com.nimbusds.oauth2.sdk.ResponseType;
|
||||
import com.nimbusds.oauth2.sdk.Scope;
|
||||
import com.nimbusds.oauth2.sdk.SerializeException;
|
||||
import com.nimbusds.oauth2.sdk.TokenErrorResponse;
|
||||
import com.nimbusds.oauth2.sdk.TokenRequest;
|
||||
import com.nimbusds.oauth2.sdk.TokenResponse;
|
||||
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
|
||||
import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
|
||||
import com.nimbusds.oauth2.sdk.auth.Secret;
|
||||
import com.nimbusds.oauth2.sdk.http.HTTPRequest;
|
||||
import com.nimbusds.oauth2.sdk.http.HTTPResponse;
|
||||
import com.nimbusds.oauth2.sdk.id.ClientID;
|
||||
import com.nimbusds.oauth2.sdk.id.State;
|
||||
@ -44,7 +46,8 @@ import com.nimbusds.openid.connect.sdk.AuthenticationResponse;
|
||||
import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser;
|
||||
import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
|
||||
import com.nimbusds.openid.connect.sdk.Nonce;
|
||||
import com.nimbusds.openid.connect.sdk.OIDCAccessTokenResponse;
|
||||
import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
|
||||
import com.nimbusds.openid.connect.sdk.OIDCTokenResponseParser;
|
||||
import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
|
||||
import com.nimbusds.openid.connect.sdk.UserInfoRequest;
|
||||
|
||||
@ -168,10 +171,9 @@ public class OpenIdConnector extends SsoConnector {
|
||||
AuthenticationResponse authenticationResponse = AuthenticationResponseParser.parse(
|
||||
new URI(request.getRequestURI() + "?" + request.getQueryString()));
|
||||
if (authenticationResponse instanceof AuthenticationErrorResponse) {
|
||||
throw buildException(((AuthenticationErrorResponse)authenticationResponse).getErrorObject());
|
||||
throw buildException(authenticationResponse.toErrorResponse().getErrorObject());
|
||||
} else {
|
||||
AuthenticationSuccessResponse authenticationSuccessResponse =
|
||||
(AuthenticationSuccessResponse)authenticationResponse;
|
||||
AuthenticationSuccessResponse authenticationSuccessResponse = authenticationResponse.toSuccessResponse();
|
||||
|
||||
String state = (String) Session.get().getAttribute(SESSION_ATTR_STATE);
|
||||
|
||||
@ -186,33 +188,25 @@ public class OpenIdConnector extends SsoConnector {
|
||||
ClientAuthentication clientAuth = new ClientSecretBasic(clientID, clientSecret);
|
||||
TokenRequest tokenRequest = new TokenRequest(
|
||||
new URI(getCachedProviderMetadata().getTokenEndpoint()), clientAuth, codeGrant);
|
||||
HTTPResponse httpResponse = tokenRequest.toHTTPRequest().send();
|
||||
if (httpResponse.getStatusCode() == HTTPResponse.SC_OK) {
|
||||
JSONObject jsonObject = httpResponse.getContentAsJSONObject();
|
||||
if (jsonObject.get("error") != null)
|
||||
throw buildException(TokenErrorResponse.parse(jsonObject).getErrorObject());
|
||||
else
|
||||
return processTokenResponse(OIDCAccessTokenResponse.parse(jsonObject));
|
||||
} else {
|
||||
ErrorObject error = TokenErrorResponse.parse(httpResponse).getErrorObject();
|
||||
if (error != null) {
|
||||
throw buildException(error);
|
||||
} else {
|
||||
String message = String.format("Error requesting OIDC token: http status: %d",
|
||||
httpResponse.getStatusCode());
|
||||
throw new AuthenticationException(message);
|
||||
}
|
||||
}
|
||||
|
||||
HTTPRequest httpRequest = tokenRequest.toHTTPRequest();
|
||||
httpRequest.setAccept(ContentType.APPLICATION_JSON.toString());
|
||||
TokenResponse tokenResponse = OIDCTokenResponseParser.parse(httpRequest.send());
|
||||
|
||||
if (tokenResponse.indicatesSuccess())
|
||||
return processTokenResponse((OIDCTokenResponse)tokenResponse.toSuccessResponse());
|
||||
else
|
||||
throw buildException(tokenResponse.toErrorResponse().getErrorObject());
|
||||
}
|
||||
} catch (ParseException | URISyntaxException|SerializeException|IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected SsoAuthenticated processTokenResponse(OIDCAccessTokenResponse tokenSuccessResponse) {
|
||||
protected SsoAuthenticated processTokenResponse(OIDCTokenResponse tokenResponse) {
|
||||
try {
|
||||
JWT idToken = tokenSuccessResponse.getIDToken();
|
||||
ReadOnlyJWTClaimsSet claims = idToken.getJWTClaimsSet();
|
||||
JWT idToken = tokenResponse.getOIDCTokens().getIDToken();
|
||||
JWTClaimsSet claims = idToken.getJWTClaimsSet();
|
||||
|
||||
if (!claims.getIssuer().equals(getCachedProviderMetadata().getIssuer()))
|
||||
throw new AuthenticationException("Inconsistent issuer in provider metadata and ID token");
|
||||
@ -227,7 +221,7 @@ public class OpenIdConnector extends SsoConnector {
|
||||
|
||||
String subject = claims.getSubject();
|
||||
|
||||
BearerAccessToken accessToken = (BearerAccessToken) tokenSuccessResponse.getAccessToken();
|
||||
BearerAccessToken accessToken = tokenResponse.getOIDCTokens().getBearerAccessToken();
|
||||
|
||||
UserInfoRequest userInfoRequest = new UserInfoRequest(
|
||||
new URI(getCachedProviderMetadata().getUserInfoEndpoint()), accessToken);
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
package io.onedev.server.product;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class Test {
|
||||
|
||||
@org.junit.Test
|
||||
public void test() throws IOException {
|
||||
public void test() {
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user