From b58d4ba85a510a16994376f4f6e00ffcbcf61d53 Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Fri, 8 Dec 2017 15:09:33 -0800 Subject: [PATCH 01/10] Not officially supported Google product --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 487c06d..c341369 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # JWTs for Java + This is not an officially supported Google product [![CircleCI](https://img.shields.io/circleci/project/github/auth0/java-jwt.svg?style=flat-square)](https://circleci.com/gh/auth0/java-jwt/tree/master) From c937d6829ca5537fb2423a588a12075605ae8f73 Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Wed, 10 Jan 2018 13:51:18 -0800 Subject: [PATCH 02/10] Oicclient --- lib/build.gradle | 5 +- lib/src/main/java/oiccli/AES.java | 137 ++++++ lib/src/main/java/oiccli/ErrorMessage.java | 7 + lib/src/main/java/oiccli/HTTP/Http.java | 47 ++ lib/src/main/java/oiccli/HTTP/Response.java | 106 +++++ lib/src/main/java/oiccli/Service.java | 409 ++++++++++++++++++ lib/src/main/java/oiccli/State.java | 157 +++++++ lib/src/main/java/oiccli/StringUtil.java | 32 ++ lib/src/main/java/oiccli/Util.java | 247 +++++++++++ .../java/oiccli/client_auth/BearerBody.java | 36 ++ .../java/oiccli/client_auth/BearerHeader.java | 63 +++ .../oiccli/client_auth/ClientSecretBasic.java | 83 ++++ .../oiccli/client_auth/ClientSecretJwt.java | 16 + .../oiccli/client_auth/ClientSecretPost.java | 27 ++ .../client_auth/JWSAuthenticationMethod.java | 118 +++++ .../oiccli/client_auth/PrivateKeyJwt.java | 21 + .../java/oiccli/client_info/ClientInfo.java | 312 +++++++++++++ .../java/oiccli/client_info/SignEncAlgs.java | 5 + .../main/java/oiccli/client_info/Usage.java | 5 + .../client_info/VerifyAlgSupportType.java | 5 + .../client_info/VerifyAlgSupportUsage.java | 5 + .../main/java/oiccli/exceptions/AESError.java | 7 + .../exceptions/AuthenticationFailure.java | 7 + .../oiccli/exceptions/ConfigurationError.java | 7 + .../java/oiccli/exceptions/ExpiredToken.java | 7 + .../oiccli/exceptions/MissingEndpoint.java | 7 + .../oiccli/exceptions/MissingParameter.java | 7 + .../java/oiccli/exceptions/NoMatchingKey.java | 7 + .../java/oiccli/exceptions/OicCliError.java | 7 + .../oiccli/exceptions/ParameterError.java | 7 + .../oiccli/exceptions/UnsupportedType.java | 7 + .../java/oiccli/exceptions/ValueError.java | 7 + .../oiccli/exceptions/WrongContentType.java | 7 + .../main/java/oiccli/service/AccessToken.java | 26 ++ .../java/oiccli/service/Authorization.java | 121 ++++++ lib/src/main/java/oiccli/service/CheckID.java | 31 ++ .../java/oiccli/service/CheckSession.java | 29 ++ .../main/java/oiccli/service/EndSession.java | 41 ++ .../oiccli/service/ProviderInfoDiscovery.java | 125 ++++++ .../java/oiccli/service/Registration.java | 64 +++ lib/src/main/java/oiccli/service/Service.java | 37 ++ .../main/java/oiccli/service/UserInfo.java | 162 +++++++ 42 files changed, 2562 insertions(+), 1 deletion(-) create mode 100644 lib/src/main/java/oiccli/AES.java create mode 100644 lib/src/main/java/oiccli/ErrorMessage.java create mode 100644 lib/src/main/java/oiccli/HTTP/Http.java create mode 100644 lib/src/main/java/oiccli/HTTP/Response.java create mode 100644 lib/src/main/java/oiccli/Service.java create mode 100644 lib/src/main/java/oiccli/State.java create mode 100644 lib/src/main/java/oiccli/StringUtil.java create mode 100644 lib/src/main/java/oiccli/Util.java create mode 100644 lib/src/main/java/oiccli/client_auth/BearerBody.java create mode 100644 lib/src/main/java/oiccli/client_auth/BearerHeader.java create mode 100644 lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java create mode 100644 lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java create mode 100644 lib/src/main/java/oiccli/client_auth/ClientSecretPost.java create mode 100644 lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java create mode 100644 lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java create mode 100644 lib/src/main/java/oiccli/client_info/ClientInfo.java create mode 100644 lib/src/main/java/oiccli/client_info/SignEncAlgs.java create mode 100644 lib/src/main/java/oiccli/client_info/Usage.java create mode 100644 lib/src/main/java/oiccli/client_info/VerifyAlgSupportType.java create mode 100644 lib/src/main/java/oiccli/client_info/VerifyAlgSupportUsage.java create mode 100644 lib/src/main/java/oiccli/exceptions/AESError.java create mode 100644 lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java create mode 100644 lib/src/main/java/oiccli/exceptions/ConfigurationError.java create mode 100644 lib/src/main/java/oiccli/exceptions/ExpiredToken.java create mode 100644 lib/src/main/java/oiccli/exceptions/MissingEndpoint.java create mode 100644 lib/src/main/java/oiccli/exceptions/MissingParameter.java create mode 100644 lib/src/main/java/oiccli/exceptions/NoMatchingKey.java create mode 100644 lib/src/main/java/oiccli/exceptions/OicCliError.java create mode 100644 lib/src/main/java/oiccli/exceptions/ParameterError.java create mode 100644 lib/src/main/java/oiccli/exceptions/UnsupportedType.java create mode 100644 lib/src/main/java/oiccli/exceptions/ValueError.java create mode 100644 lib/src/main/java/oiccli/exceptions/WrongContentType.java create mode 100644 lib/src/main/java/oiccli/service/AccessToken.java create mode 100644 lib/src/main/java/oiccli/service/Authorization.java create mode 100644 lib/src/main/java/oiccli/service/CheckID.java create mode 100644 lib/src/main/java/oiccli/service/CheckSession.java create mode 100644 lib/src/main/java/oiccli/service/EndSession.java create mode 100644 lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java create mode 100644 lib/src/main/java/oiccli/service/Registration.java create mode 100644 lib/src/main/java/oiccli/service/Service.java create mode 100644 lib/src/main/java/oiccli/service/UserInfo.java diff --git a/lib/build.gradle b/lib/build.gradle index 2a7694c..68c57fe 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -37,8 +37,11 @@ dependencies { compile 'com.fasterxml.jackson.core:jackson-databind:2.9.2' compile 'commons-codec:commons-codec:1.11' compile 'com.google.code.gson:gson:2.8.2' + compile group: 'org.apache.commons', name: 'commons-text', version: '1.1' + compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.6.1' + compile 'junit:junit:4.12' + compile "com.google.guava:guava:16+" testCompile 'org.bouncycastle:bcprov-jdk15on:1.58' - testCompile 'junit:junit:4.12' testCompile 'net.jodah:concurrentunit:0.4.3' testCompile 'org.hamcrest:java-hamcrest:2.0.0.0' testCompile 'org.mockito:mockito-core:2.11.0' diff --git a/lib/src/main/java/oiccli/AES.java b/lib/src/main/java/oiccli/AES.java new file mode 100644 index 0000000..5900701 --- /dev/null +++ b/lib/src/main/java/oiccli/AES.java @@ -0,0 +1,137 @@ +package oiccli; + +import org.junit.Assert; +import org.bouncycastle.util.encoders.Base64; +import oiccli.exceptions.AESError; + +import java.util.Arrays; +import java.util.List; + +public class AES { + + private static final int BLOCK_SIZE = 16; + private byte[] key; + private int mode; + private byte[] iv; + private AES kernel; + + public AES(byte[] key, byte[] iv, int mode) { + assert key instanceof byte[]; + assert iv instanceof byte[]; + this.key = key; + this.mode = mode; + this.iv = iv; + this.kernel = new AES(this.key, this.mode, this.iv); + } + + public static List buildCipher(byte[] key, byte[] iv, String alg) + throws AESError { + String[] algArr = alg.split("_"); + + if (iv == null) { + + } else { + Assert.assertTrue(key.length == 16); //AES.blockSize + } + + int bits = Integer.parseInt(algArr[1]); + if (bits != 128 && bits != 192 && bits != 256) { + throw new AESError("Unsupported key length"); + } + + try { + Assert.assertTrue(key.length == bits >> 3); + } catch (AssertionError error) { + throw new AESError("Wrong key length"); + } + + /* + CONVERT THIS TO JAVA + + try: + return AES.new(tobytes(key), POSTFIX_MODE[cmode], tobytes(iv)), iv + except KeyError: + raise AESError("Unsupported chaining mode")*/ + } + + public static List buildCipher(byte[] key, byte[] iv) throws AESError { + buildCipher(key, iv, "aes_128_cbc"); + return null; + } + + public static void encrypt(byte[] key, String msg, byte[] iv, String alg, String padding, + boolean shouldBase64Encrypt, int blockSize) { + + int blockSizeLocal; + if (padding.equals("PKCS#7")) { + blockSizeLocal = blockSize; + } else if (padding.equals("PKCS#5")) { + blockSizeLocal = 8; + } else { + blockSizeLocal = 0; + } + + if (blockSizeLocal != 0) { + int pLength = blockSizeLocal - (msg.length() % blockSizeLocal); + char character = (char) pLength; + msg += (character * pLength); + } + + try { + List buildCipher = buildCipher(key, iv, alg); + } catch (AESError aesError) { + aesError.printStackTrace(); + } + + if (shouldBase64Encrypt) { + Base64.encode(cmsg); + } else { + return cmsg; + } + } + + public static void encrypt(byte[] key, String msg) { + return encrypt(key, msg, null, "aes_128_cbc", "PKCS#7", true, BLOCK_SIZE); + } + + public static byte[] decrypt(byte[] key, String msg, byte[] iv, String padding, boolean shouldBase64Decrypt) throws AESError { + byte[] data; + if (shouldBase64Decrypt) { + data = Base64.decode(msg); + } else { + data = msg.getBytes(); + } + + byte[] ivByteArr = Arrays.copyOfRange(data, 0, 16); + if (iv != null) { + Assert.assertEquals(iv, ivByteArr); + } + List cipherList = buildCipher(key, iv); + //insert python code + byte[] decrpytArr = cipher.decrypt(data); + byte[] res = Arrays.copyOfRange(decrpytArr, 16, decrpytArr.length); + + if (padding.equals("PKCS#5") || padding.equals("PKCS#7")) { + res = Arrays.copyOfRange(res, 0, res[res.length - 1]); + } + + return Base64.decode(res); + } + + public static void decrypt(byte[] key, String msg, byte[] iv) { + return decrypt(key, msg, null, "PKCS#7", true); + } + + public void addAssociatedData(String data) { + data = new String(Base64.encode(data.getBytes())); + this.kernel.update(data); + } + + public List encryptAndTag(byte[] clearData) { + return this.kernel.encryptAndDigest(clearData); + } + + public void decryptAndVerify(byte[] cypherData, byte[] tag) { + return this.kernel.decryptAndVerify(cypherData, tag); + } +} diff --git a/lib/src/main/java/oiccli/ErrorMessage.java b/lib/src/main/java/oiccli/ErrorMessage.java new file mode 100644 index 0000000..c187954 --- /dev/null +++ b/lib/src/main/java/oiccli/ErrorMessage.java @@ -0,0 +1,7 @@ +package oiccli; + +import com.auth0.jwt.creators.Message; + +public class ErrorMessage extends Message{ + +} diff --git a/lib/src/main/java/oiccli/HTTP/Http.java b/lib/src/main/java/oiccli/HTTP/Http.java new file mode 100644 index 0000000..414f056 --- /dev/null +++ b/lib/src/main/java/oiccli/HTTP/Http.java @@ -0,0 +1,47 @@ +package oiccli.HTTP; + +import java.util.HashMap; +import java.util.Map; + +public class Http { + + private String caCerts; + private Map requestArgs; + private KeyJar keyJar; + private FileCookieJar cookieJar; + private Object events; + private Object reqCallback; + + public Http(String caCerts, boolean shouldVerifySSL, KeyJar keyjar, String clientCert) { + this.caCerts = caCerts; + this.requestArgs = new HashMap() {{ + put("allowRedirects", false); + }}; + this.keyJar = keyjar; //or KeyJar(verify_ssl=verify_ssl) + //this.cookiejar = FileCookieJar() + if (caCerts != null) { + if (!shouldVerifySSL) { + throw new ValueError("conflict: ca_certs defined, but verify_ssl is False"); + } + this.requestArgs.put("verify", caCerts); + } else if (shouldVerifySSL) { + this.requestArgs.put("verify", true); + } else { + this.requestArgs.put("verify", false); + } + this.events = null; + this.reqCallback = null; + + if (clientCert != null) { + this.requestArgs.put("cert", clientCert); + } + } + + public Map getCookies() { + Map cookiesMap = new HashMap<>(); + for (cookieJar.getCookies().) + + + return cookiesMap; + } +} diff --git a/lib/src/main/java/oiccli/HTTP/Response.java b/lib/src/main/java/oiccli/HTTP/Response.java new file mode 100644 index 0000000..634f4bd --- /dev/null +++ b/lib/src/main/java/oiccli/HTTP/Response.java @@ -0,0 +1,106 @@ +package oiccli.HTTP; + +import com.auth0.jwt.creators.Message; +import oiccli.StringUtil; + +import java.util.*; + +public class Response { + + private static final List successfulCodes = + Arrays.asList(200, 201, 202, 203, 204, 205, 206); + private static Map corsHeaders = new + HashMap() {{ + put("Access-Control-Allow-Origin", "*"); + put("Access-Control-Allow-Methods", "GET"); + put("Access-Control-Allow-Headers", "Authorization"); + }}; + private String status = "200 OK"; + private String contentType = "text/html"; + private Object template; + private Object makoTemplate; + private Object makoLookup; + private Message message; + private List> headers; + + public Response(Message message, Map args) { + this.status = args.get("status"); + this.response = args.get("response"); + this.template = args.get("template"); + this.makoTemplate = args.get("makoTemplate"); + this.makoLookup = args.get("templateLookup"); + + this.message = message; + this.headers = new ArrayList<>(); + this.headers.add(args.get("headers"), new List<>()); + this.contentType = args.get("content"); + + } + + private List getResponse(String message, Map args) { + if (StringUtil.isNotNullAndNotEmpty(message)) { + if (message.contains("", "</script>"); + } + } + + if (this.template != null) { + for (Map hMap : headers) { + if (hMap.containsKey("Content-type") && hMap.get("Content-type").equals("application/json")) { + return Arrays.asList(message); + } else { + //return [str(self.template % message).encode("utf-8")] + } + } + } else if (this.makoLookup != null && this.makoTemplate != null) { + args.put("message", message); + Object mte = this.makoLookup.getTemplate(this.makoTemplate); + return Arrays.asList(mte.render(args)); + } else { + for (String type : this._c_types()) { + if (type.startsWith("image/") || type.equals("application/x-gzip")) { + return Arrays.asList(message); + } + } + } + + + } + + public Map info() { + Map hMap = new HashMap() {{ + put("status", this.status); + put("headers", this.headers); + put("message", this.message); + }}; + + return hMap; + } + + public void addHeader(Map value) { + this.headers.add(value); + } + + public Response reply(Map args) { + return this.response(message, args); + } + + public List cTypes() { + List cTypes = new ArrayList<>(); + Iterator it; + Map.Entry pair; + for (Map index : this.headers) { + it = index.entrySet().iterator(); + while (it.hasNext()) { + pair = (Map.Entry) it.next(); + if (((String) pair.getKey()).equals("Content-type")) { + cTypes.add((String) pair.getValue()); + } + it.remove(); + } + } + } + + +} diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java new file mode 100644 index 0000000..e505a0f --- /dev/null +++ b/lib/src/main/java/oiccli/Service.java @@ -0,0 +1,409 @@ +package oiccli; + +import com.auth0.jwt.creators.Message; +import oiccli.HTTP.Response; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingEndpoint; +import oiccli.exceptions.OicCliError; +import oiccli.exceptions.UnsupportedType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.ws.http.HTTPException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.*; + +public class Service { + + private final static Logger logger = LoggerFactory.getLogger(Service.class); + private static final List successfulCodes = + Arrays.asList(200, 201, 202, 203, 204, 205, 206); + private static final List specialArgs = Arrays.asList("authenticationEndpoint", "algs"); + private static final Map attributes = new HashMap() {{ + put("version", null); + put("name", ""); + put("value", null); + put("port", null); + put("isPortSpecified", false); + put("domain", ""); + put("isDomainSpecified", false); + put("domainInitialDot", false); + put("path", ""); + put("isPathSpecified", false); + put("isSecure", false); + put("expires", null); + put("shouldDiscard", true); + put("comment", null); + put("commentUrl", null); + put("rest", ""); + put("rfc2109", true); + }}; + + private Message msgType; + private Message responseCls; + private ErrorResponse errorResponse; + private String endpointName = ""; + private boolean isSynchronous = true; + private String request = ""; + private String defaultAuthenticationMethod = ""; + private String httpMethod = "GET"; + private String bodyType = "urlencoded"; + private String responseBodyType = "json"; + private String endpoint = ""; + private String httpLib; + private KeyJar keyJar; + private String clientAuthenticationMethod; + private List events; + private Map defaultRequestArgs; + private List preConstruct; + private List postConstruct; + private List postParseResponse; + + + public Service(String httpLib, KeyJar keyJar, String clientAuthenticationMethod, Map args) { + this.httpLib = httpLib; + this.keyJar = keyJar; + this.clientAuthenticationMethod = clientAuthenticationMethod; + this.events = new ArrayList<>(); + this.endpoint = ""; + this.defaultRequestArgs = new HashMap<>(); + this.preConstruct = new ArrayList<>(); + this.postConstruct = new ArrayList<>(); + this.postParseResponse = new ArrayList<>(); + this.setUp(); + } + + public Map parseArgs(ClientInfo clientInfo, Map args) throws NoSuchFieldException, IllegalAccessException { + Map arArgs = new HashMap<>(args); + Object value; + for (String property : this.msgType.cParam.keySet()) { + if (!arArgs.containsKey(property)) { + value = clientInfo.getClass().getField(property).get(property); + if (value != null) { + arArgs.put(property, value); + } else { + arArgs.put(property, this.defaultRequestArgs.get(property)); + } + } + } + + return arArgs; + } + + public List> doPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + Map postArgs = new HashMap<>(); + for (Object method : this.preConstruct) { + /*request_args, _post_args = meth(cli_info, request_args, **kwargs) + post_args.update(_post_args)*/ + } + + return Arrays.asList(requestArgs, postArgs); + } + + public Message doPostConstruct(ClientInfo clientInfo, Map requestArgs, Map postArgs) { + + } + + public void doPostParseResponse(Message response, ClientInfo clientInfo, String state, Map args) { + /* + for meth in self.post_parse_response: + meth(resp, cli_info, state=state, **kwargs) + */ + } + + public Message constructMessage(ClientInfo clientInfo, Map requestArgs, Map args) throws NoSuchFieldException, IllegalAccessException { + + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + List> returnedArgs = this.doPreConstruct(clientInfo, requestArgs, args); + + if (!this.msgType.c_param.containsKey("state")) { + args.remove("state"); + } + + Map argsParam = this.parseArgs(clientInfo, requestArgs); + this.msgType(argsParam); + + return this.doPostConstruct(clientInfo, requestArgs, returnedArgs.get(1)); + } + + public String getEndpoint(Map args) throws MissingEndpoint { + String uri = args.get("endpoint"); + + if (uri == null) { + uri = this.endpoint; + } + + if (uri == null || uri.isEmpty()) { + throw new MissingEndpoint("No endpoint specified"); + } + + return uri; + } + + public Map uriAndBody(Message cis, String method, Map requestArgs, Map args) throws UnsupportedEncodingException, UnsupportedType { + Map response = null; + try { + String uri = this.getEndpoint(requestArgs); + response = Util.getOrPost(uri, method, cis, args); + response.put("cis", cis); + Map hMap = new HashMap<>(); + hMap.put("headers", response.get("headers")); + response.put("h_args", hMap); + } catch (MissingEndpoint missingEndpoint) { + missingEndpoint.printStackTrace(); + } + + return response; + } + + public Map initAuthenticationMethod(Message cis, ClientInfo clientInfo, String authenticationMethod, + Map requestArgs, Map args) { + return initAuthenticationMethod(cis, clientInfo, authenticationMethod, requestArgs, null, args); + } + + public Map initAuthenticationMethod(Message cis, ClientInfo clientInfo, String authenticationMethod, + Map requestArgs, Map httpArgs, Map args) { + if (httpArgs == null) { + httpArgs = new HashMap<>(); + } + + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + if (authenticationMethod != null) { + //return this.client_authn_method[authn_method]().construct( + // cis, cli_info, request_args, http_args, **kwargs); + } else { + return httpArgs; + } + } + + public ClientInfo requestInfo(ClientInfo clientInfo, String method, Map requestArgs, + String bodyType, String authenticationMethod, boolean lax, Map args) throws NoSuchFieldException, IllegalAccessException { + if (method == null) { + method = this.httpMethod; + } + + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + Map hMap = new HashMap<>(); + for (String key : args.keySet()) { + if (args.get(key) != null && !specialArgs.contains(key)) { + hMap.put(key, args.get(key)); + } + } + + Message cis = this.constructMessage(clientInfo, requestArgs, args); + + if (this.events != null) { + this.events.store("Protocol request", cis); + } + + cis.setLax(lax); + Map hArg = new HashMap<>(); + if (authenticationMethod != null) { + hArg = this.initAuthenticationMethod(cis, clientInfo, authenticationMethod, requestArgs, args); + } + + if (hArg != null) { + if (args.containsKey("headers")) { + args.get("headers").update(hArg.get("headers")); + } else { + args.put("headers", hArg.get("headers")); + } + } + + if (bodyType.equals("json")) { + args.put("contentType", "application/json"); + } + + return this.uriAndBody(cis, method, requestArgs, args); + } + + public ClientInfo updateHttpArgs(Map httpArgs, ClientInfo info) { + Map hArgs = info.get("hArgs"); + if (hArgs == null) { + hArgs = new HashMap<>(); + } + + if (httpArgs == null) { + httpArgs = hArgs; + } else { + httpArgs.update(info.get("h_args")); + } + + info.put("httpArgs", httpArgs); + return info; + } + + public ClientInfo doRequestInit(ClientInfo clientInfo, String bodyType, String method, String authenticationMethod, + Map requestArgs, Map httpArgs, Map args) throws NoSuchFieldException, IllegalAccessException { + if (method == null || method.isEmpty()) { + method = this.httpMethod; + } + if (authenticationMethod == null || authenticationMethod.isEmpty()) { + authenticationMethod = this.defaultAuthenticationMethod; + } + if (bodyType == null || bodyType.isEmpty()) { + bodyType = this.bodyType; + } + + ClientInfo info = this.requestInfo(clientInfo, method, requestArgs, bodyType, authenticationMethod, false, args); + + return this.updateHttpArgs(httpArgs, info); + } + + public String getUrlInfo(String info) throws URISyntaxException { + String query = null, fragment = null; + if (info.contains("?") || info.contains("#")) { + URI uri = new URI(info); + query = uri.getQuery(); + fragment = uri.getFragment(); + } + + if (StringUtil.isNotNullAndNotEmpty(query)) { + info = query; + } else { + info = fragment; + } + + return info; + } + + public Message parseResponse(String info, ClientInfo clientInfo, String sFormat, String state, + Map args) throws URISyntaxException, OicCliError { + logger.debug("Response format: " + sFormat); + + if (sFormat.equals("urlencoded")) { + info = this.getUrlInfo(info); + } + + if (this.events != null) { + this.events.store("Response", info); + } + + logger.debug("Response cls: " + this.responseCls.getClass()); + + Message response = this.responseCls.deserialize(info, sFormat, args); + + String message = "Initial response parsing => \"{}\""; + logger.debug(message.format(response.toDict())); + + if (this.events != null) { + this.events.store("Protocol Response", response); + } + + List errorMsgs; + if (response.containsKey("error") && !(response instanceof ErrorResponse)) { + response = null; + errorMsgs = Arrays.asList(this.errorResponse); + + + for (ErrorResponse errorMsg : errorMsgs) { + response = errorMsg.deserialize(info, sFormat); + response.verify(); + break; + } + + logger.debug("Error response: " + response); + } else { + args.put("clientId", clientInfo.getClientId()); + args.put("issuer", clientInfo.getIssuer()); + + if (!args.containsKey("key") && !args.containsKey("keyJar")) { + args.put("keyJar", keyJar); + } + + logger.debug("Verify response with " + args); + + boolean isVerificationSuccessful = response.verify(args); + if (!isVerificationSuccessful) { + logger.error("Verification of the response failed"); + throw new OicCliError("Verification of the response failed"); + } + + if (response.getType().equals("AuthorizationResponse") && response.getScope() == null) { + response.setScope(args.get("scope")); + } + } + + if (response == null) { + this.doPostParseResponse(response, clientInfo, state, args); + } + + return response; + } + + public ErrorResponse parseErrorMessage(Response response, String bodyType) { + String bodyTypeResult; + if (bodyType.equals("txt")) { + bodyTypeResult = "urlencoded"; + } else { + bodyTypeResult = bodyType; + } + + ErrorResponse errorResponse = this.errorResponse.deserialize(response.getText(), bodyType); + errorResponse.verify(); + + return errorResponse; + } + + public String getValueType(Response response, String bodyType) { + if (StringUtil.isNotNullAndNotEmpty(bodyType)) { + return this.verifyHeader(response, bodyType); + } else { + return "urlencoded"; + } + } + + public ErrorResponse parseRequestResponse(Response response, ClientInfo clientInfo, String responseBodyType, + String state, Map args) { + int statusCode = response.getStatusCode(); + if (successfulCodes.contains(statusCode)) { + logger.debug("Response body type " + responseBodyType); + String valueType = this.getValueType(response, responseBodyType); + logger.debug("Successful response " + response.getText()); + return this.parseResponse(response.getText(), clientInfo, valueType, state, args); + } else if (statusCode == 302 || statusCode == 303) { + return response; + } else if (statusCode == 500) { + logger.error("(" + statusCode + ")" + response.getText()); + throw new ParseException("ERROR: Something went wrong " + response.getText()); + } else if (statusCode >= 400 && statusCode < 500) { + logger.error("Error response (" + statusCode + "): " + response.getText()); + String valueType = this.getValueType(response, responseBodyType); + return this.parseErrorMessage(response, valueType); + } else { + logger.error("Error response (" + statusCode + "):" + response.getText()); + throw new HTTPException("HTTP ERROR: " + response.getText() + "[" + statusCode + "]" + " on " + response.getUrl()); + } + } + + public ErrorResponse serviceRequest(String url, String method, String body, String responseBodyType, Map httpArgs, + ClientInfo clientInfo, Map args) { + if (httpArgs == null) { + httpArgs = new HashMap<>(); + } + + logger.debug("Doing request with: URL: " + url + ", method: " + method + ", data: " + body + ", https_args: " + httpArgs); + Response response = this.httpLib(url, method, body, httpArgs); + + if (!args.containsKey("keyjar")) { + args.put("keyjar", this.keyJar); + } + if (responseBodyType == null) { + responseBodyType = this.responseBodyType; + } + + return this.parseRequestResponse(response, clientInfo, responseBodyType, "", args); + } +} diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java new file mode 100644 index 0000000..dda8715 --- /dev/null +++ b/lib/src/main/java/oiccli/State.java @@ -0,0 +1,157 @@ +package oiccli; + +import oiccli.exceptions.ExpiredToken; + +import java.util.HashMap; +import java.util.Map; + +public class State { + + private String clientId; + private Database db; + private int lifetime; + + public State(String clientId, Database db, String dbName, int lifetime) { + this.clientId = clientId; + if (db == null) { + if (StringUtil.isNotNullAndNotEmpty(dbName)) { + this.db = shelve.open(dbName, true); + } else { + this.db = new Database(); + } + } else { + this.db = db; + } + this.lifetime = lifetime; + } + + public String createState(final String receiver, Object request) { + String state = StringUtil.generateRandomString(24); + final long now = System.currentTimeMillis(); + Map info = new HashMap() {{ + put("clientId", clientId); + put("as", receiver); + put("iat", now); + }}; + switch (state) { + case "1": + this.db.set1(info); + break; + case "2": + this.db.set2(info); + break; + case "3": + this.db.set3(info); + break; + } + + return state; + } + + public Map> updateTokenInfo(Map> info, AuthorizationResponse authorizationResponse) { + Map hMap = info.get("token"); + if (hMap == null) { + hMap = new HashMap<>(); + } + + String token = authorizationResponse.getAccessToken(); + hMap.put("accessToken", token); + Integer expiresAtInteger = authorizationResponse.getExpiresIn(); + int expiresAt; + if (expiresAtInteger != null) { + expiresAt = expiresAtInteger.intValue(); + hMap.put("exp", System.currentTimeMillis() + expiresAt); + hMap.put("expiresIn", expiresAt); + } else { + hMap.put("exp", System.currentTimeMillis() + ((Long) hMap.get("expiresIn")).longValue()); + } + + hMap.put("tokenType", authorizationResponse.getTokenType()); + hMap.put("scope", authorizationResponse.getScope()); + + info.put("token", hMap); + + return info; + } + + public Map> addMessageInfo(AuthorizationResponse authorizationResponse, String state) { + if (state == null) { + state = authorizationResponse.getState(); + } + + //_info = self[state] what are all the available types so i can create a switch/case? + + info.put("code", authorizationResponse.getCode()); + this.updateTokenInfo(info, authorizationResponse); + + info.put("idToken", authorizationResponse.getIdToken()); + info.put("refreshToken", authorizationResponse.getRefreshToken()); + + switch (state) { + case "1": + this.db.set1(info); + break; + case "2": + this.db.set2(info); + break; + case "3": + this.db.set3(info); + break; + } + + return info; + } + + public Map addInfo(String state, Map args) { + Map info = this.get(state); + info.update(args); + + switch (state) { + case "1": + this.db.set1(info); + break; + case "2": + this.db.set2(info); + break; + case "3": + this.db.set3(info); + break; + } + + return info; + } + + public Map getTokenInfo(String state, long now) throws ExpiredToken { + //_tinfo = self[state]['token'] + //_exp = _tinfo['exp'] + if (now == 0) { + now = System.currentTimeMillis(); + } + if (now > _exp) { + throw new ExpiredToken("Passed best before"); + } + return _tinfo; + } + + public Map getRequestArgs(String state, ABCMeta request, int now) throws ExpiredToken { + Map info = state.getState(state); + Map requestArgs = new HashMap<>(); + for (String claim : request.c_param) { + if (claim.equals("accessToken")) { + Map tInfo = this.getTokenInfo(state, now); + if (tInfo == null) { + continue; + } + requestArgs.put(claim, tInfo.get("accessToken")); + } else { + requestArgs.put(claim, info.get(claim)); + } + } + + return requestArgs; + } + + public String getIdToken(String state) { + return this.get(state).get("idToken"); + } +} diff --git a/lib/src/main/java/oiccli/StringUtil.java b/lib/src/main/java/oiccli/StringUtil.java new file mode 100644 index 0000000..02bbf6f --- /dev/null +++ b/lib/src/main/java/oiccli/StringUtil.java @@ -0,0 +1,32 @@ +package oiccli; + +import org.apache.commons.text.CharacterPredicates; +import org.apache.commons.text.RandomStringGenerator; + +public class StringUtil { + + public static String generateRandomString(int length) { + return new RandomStringGenerator.Builder() + .withinRange('0', 'z') + .filteredBy(CharacterPredicates.LETTERS, CharacterPredicates.DIGITS) + .build().generate(length); + } + + public static String alg2keytype(String algorithm) { + if (algorithm == null || algorithm.toLowerCase().equals("none")) { + return "none"; + } else if (algorithm.startsWith("RS") || algorithm.startsWith("PS")) { + return "RSA"; + } else if (algorithm.startsWith("HS") || algorithm.startsWith("A")) { + return "oct"; + } else if (algorithm.startsWith("ES") || algorithm.startsWith("ECDH-ES")) { + return "EC"; + } else { + return null; + } + } + + public static boolean isNotNullAndNotEmpty(String s) { + return s != null && !s.isEmpty(); + } +} diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java new file mode 100644 index 0000000..326fd5f --- /dev/null +++ b/lib/src/main/java/oiccli/Util.java @@ -0,0 +1,247 @@ +package oiccli; + +import com.auth0.jwt.creators.Message; +import oiccli.exceptions.UnsupportedType; +import oiccli.exceptions.ValueError; +import oiccli.exceptions.WrongContentType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.UnsupportedEncodingException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Util { + + private static final String URL_ENCODED = "application/x-www-form-urlencoded"; + private static final String JSON_ENCODED = "application/json"; + private static final String JWT_ENCODED = "application/jwt"; + private static final String JWT = "jwt"; + private static final String JSON = "json"; + private static final String URLENCODED = "urlencoded"; + private static final String DEFAULT_POST_CONTENT_TYPE = URL_ENCODED; + Map pairs = new HashMap() {{ + put("port", "portSpecified"); + put("domain", "domainSpecified"); + put("path", "pathSpecified"); + }}; + private static final Map attributes = new HashMap() {{ + put("version", null); + put("name", ""); + put("value", null); + put("port", null); + put("portSpecified", false); + put("domain", ""); + put("domainSpecified", false); + put("domainInitialDot", false); + put("path", ""); + put("pathSpecified", false); + put("secure", false); + put("expires", null); + put("discard", true); + put("comment", null); + put("commentUrl", null); + put("rest", ""); + put("rfc2109", true); + }}; + private final static Logger logger = LoggerFactory.getLogger(Util.class); + private final static Map sortOrder = new HashMap() {{ + put("RS", 0); + put("ES", 1); + put("HS", 2); + put("PS", 3); + put("no", 4); + }}; + + public static Map getOrPost(String uri, String method, Message cis, Map args) throws UnsupportedEncodingException, UnsupportedType { + return getOrPost(uri, method, cis, "application/x-www-form-urlencoded", null, args); + } + + public static Map getOrPost(String uri, String method, Message request, String contentType, String accept, Map args) throws UnsupportedEncodingException, UnsupportedType { + Map response = new HashMap<>(); + String urlEncoded; + if (method.equals("GET") || method.equals("DELETE")) { + urlEncoded = request.toUrlEncoded(request.toString()); + if (urlEncoded.contains("?")) { + response.put("uri", uri + '&' + urlEncoded); + } else { + response.put("uri", uri + '?' + urlEncoded); + } + } else if (method.equals("POST") || method.equals("PUT")) { + response.put("uri", uri); + if (contentType.equals("application/x-www-form-urlencoded")) { + response.put("body", request.toUrlEncoded(request.toString())); + } else if (contentType.equals(JSON_ENCODED)) { + response.put("body", request.toJSON(request.toHashMap())); + } else { + throw new UnsupportedType("Unsupported content type " + contentType); + } + + Map headers = new HashMap<>(); + headers.put("Content-Type", contentType); + + if (accept != null) { + headers = new HashMap<>(); + headers.put("Accept", accept); + } + if (args.containsKey("headers")) { + //kwargs["headers"].update(header_ext) + } else { + args.put("headers", headers); + } + } else { + throw new UnsupportedType("Unsupported HTTP method " + method); + } + + return response; + } + + public static void setCookie(CookieJar cookieJar, Map cookieMap) { + Map attributesCopy; + String codedValue; + Morsel morsel; + String morselValue; + for (String cookieName : cookieMap.keySet()) { + attributesCopy = new HashMap<>(attributes); + attributesCopy.put("name", cookieName); + morsel = cookieMap.get(cookieName); + codedValue = morsel.getCodedValue(); + + if (codedValue.startsWith("\"") && codedValue.endsWith("\"")) { + attributesCopy.put("value", codedValue.substring(1, codedValue.length() - 1)); + } else { + attributesCopy.put("value", codedValue); + } + + attributesCopy.put("version", 0); + String failedAttribute = null; + try { + for (String attribute : morsel.keySet()) { + failedAttribute = attribute; + if (attributes.containsKey(attribute)) { + morselValue = morsel.get(attribute); + if (StringUtil.isNotNullAndNotEmpty(morselValue)) { + if (attribute.equals("expires")) { + attributesCopy.put(attribute, dateToTime(morselValue)); + } else { + attributesCopy.put(attribute, morselValue); + } + } else if (attribute.equals("maxAge")) { + if (StringUtil.isNotNullAndNotEmpty(morselValue)) { + attributesCopy.put("expires", dateToTime(morselValue)); + } + } + } + } + } catch (ParseException e) { + logger.info("Time format error on " + failedAttribute + " parameter in received cookie"); + continue; + } + + for (String attribute : pairs.keySet()) { + if (attributesCopy.get(attribute) != null) { + attributesCopy.put(pairs.get(attribute), true); + } + } + + if (attributesCopy.get("domain") instanceof String && StringUtil.isNotNullAndNotEmpty((String) attributesCopy.get("domain")) && ((String) attributesCopy.get("domain")).startsWith(".")) { + attributesCopy.put("domainInitialDot", true); + } + + if (morsel.getMaxAge() == 0) { + cookieJar.clear(attributesCopy.getDomain(), attributesCopy.getPath(), attributesCopy.getName()); + } else { + if (attributesCopy.containsKey("version")) { + attributesCopy.put("version", ((String) attributesCopy.get("version")).split(",")[0]); + } + + Cookie newCookie = new Cookie(); + cookieJar.setCookie(newCookie); + } + } + } + + public static boolean matchTo(String value, List valuesList) { + for (String index : valuesList) { + if (index.startsWith(value)) { + return true; + } + } + return false; + } + + public static boolean matchTo(String value, String valueExpected) { + return valueExpected.startsWith(value); + } + + public String verifyHeader(FakeResponse response, String bodyType) throws WrongContentType, ValueError { + logger.debug("Response headers: " + response.getHeaders().toString()); + logger.debug("Response txt: " + response.getText().toString()); + + String contentType = response.getHeaders().getContentType(); + if (!StringUtil.isNotNullAndNotEmpty(contentType)) { + if (!StringUtil.isNotNullAndNotEmpty(bodyType)) { + return bodyType; + } else { + return "txt"; + } + } + + logger.debug("Expected body type: " + bodyType); + + if (bodyType.equals("")) { + if (matchTo(JSON_ENCODED, contentType)) { + bodyType = JSON; + } else if (matchTo(JWT_ENCODED, contentType)) { + bodyType = JWT; + } else if (matchTo(URL_ENCODED, contentType)) { + bodyType = URLENCODED; + } else { + bodyType = "txt"; + } + } else if (bodyType.equals(JSON)) { + if (matchTo(JSON_ENCODED, contentType)) { + bodyType = JSON; + } else if (matchTo(JWT_ENCODED, contentType)) { + bodyType = JWT; + } else { + throw new WrongContentType(contentType); + } + } else if (bodyType.equals(JWT)) { + if (!matchTo(JWT_ENCODED, contentType)) { + throw new WrongContentType(contentType); + } + } else if (bodyType.equals(URLENCODED)) { + if (!matchTo(DEFAULT_POST_CONTENT_TYPE, contentType) && + !matchTo("text/plain", contentType)) { + throw new WrongContentType(contentType); + } + } else { + throw new ValueError("Unknown return format: " + bodyType); + } + + logger.debug("Got body type: " + bodyType); + return bodyType; + } + + public Integer sortSignAlgorithm(String algorithm1, String algorithm2) { + if (sortOrder.get(algorithm1.substring(0, 2)) < sortOrder.get(algorithm2.substring(0, 2))) { + return -1; + } else if (sortOrder.get(algorithm1.substring(0, 2)) > sortOrder.get(algorithm2.substring(0, 2))) { + return 1; + } else { + return algorithm1.compareTo(algorithm2); + } + } + + public static long dateToTime(String date) throws ParseException { + DateFormat inputFormat = new SimpleDateFormat("dd MMM yyy HH:mm:ss zz"); + Date d = inputFormat.parse(date); + return d.getTime(); + } +} diff --git a/lib/src/main/java/oiccli/client_auth/BearerBody.java b/lib/src/main/java/oiccli/client_auth/BearerBody.java new file mode 100644 index 0000000..aac5b72 --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/BearerBody.java @@ -0,0 +1,36 @@ +package oiccli.client_auth; + +import oiccli.exceptions.AuthenticationFailure; + +import java.util.HashMap; +import java.util.Map; + +public class BearerBody { + + public Map> construct(Map cis, CliInfo cliInfo, Map requestArgs, Map> httpArgs, + Map args) throws AuthenticationFailure { + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + if (!cis.containsKey("accessToken")) { + String accessToken = requestArgs.get("accessToken"); + if (accessToken != null) { + cis.put("accessToken", accessToken); + } else { + if (args.get("state") == null) { + String state = cliInfo.getState(); + if (state == null) { + throw new AuthenticationFailure("Missing state specification"); + } + + args.put("state", state); + } + + cis.put("accessToken", cliInfo.getStateDb().getTokenInfo(args).get("accessToken")); + } + } + + return httpArgs; + } +} diff --git a/lib/src/main/java/oiccli/client_auth/BearerHeader.java b/lib/src/main/java/oiccli/client_auth/BearerHeader.java new file mode 100644 index 0000000..dfa47e8 --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/BearerHeader.java @@ -0,0 +1,63 @@ +package oiccli.client_auth; + +import java.util.HashMap; +import java.util.Map; + +public class BearerHeader { + + public Map> construct(Map cis, CliInfo cliInfo, Map requestArgs, Map> httpArgs, + Map args) { + String accessToken; + if (cis != null) { + if (cis.containsKey("accessToken")) { + accessToken = cis.get("accessToken"); + cis.remove(accessToken); + //cis.c_param["access_token"] = SINGLE_OPTIONAL_STRING + } else { + accessToken = requestArgs.get("accessToken"); + requestArgs.remove(accessToken); + + if (accessToken != null) { + accessToken = args.get("accessToken"); + if (accessToken == null) { + //_acc_token = cli_info.state_db.get_token_info( + // **kwargs)['access_token'] + } + } + } + } else { + accessToken = args.get("accessToken"); + if (accessToken == null) { + accessToken = requestArgs.get("accessToken"); + } + } + + String bearer = "Bearer " + accessToken; + if (httpArgs == null) { + Map hMap = new HashMap<>(); + hMap.put("Authorization", bearer); + httpArgs.put("headers", hMap); + } else { + Map hMap = httpArgs.get("headers"); + if (hMap == null) { + hMap = new HashMap<>(); + } + hMap.put("Authorization", bearer); + httpArgs.put("headers", hMap); + } + + return httpArgs; + } + + public static String bearerAuth(Map req, String authentication) { + if (req.containsKey("accessToken")) { + return req.get("accessToken"); + } else { + if (authentication.startsWith("Bearer ")) { + return authentication.substring(7); + } else { + throw new IllegalArgumentException("Authentication " + authentication + " is invalid"); + } + } + } +} diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java new file mode 100644 index 0000000..6471fde --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java @@ -0,0 +1,83 @@ +package oiccli.client_auth; + +import com.auth0.jwt.jwts.JWT; + +import oiccli.StringUtil; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.text.CharacterPredicates; +import org.apache.commons.text.RandomStringGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ClientSecretBasic extends ClientAuthenticationMethod { + + private final static Logger logger = LoggerFactory.getLogger(ClientAuth.class); + + public static JWT assertionJwt(String clientId, List keys, List audience, String algorithm, int lifetime) { + long now = System.currentTimeMillis(); + String jti = StringUtil.generateRandomString(32); + + AuthToken token = new AuthToken(clientId, clientId, audience, jti, now + lifetime, now); + logger.debug("AuthnToken " + token.toString()); + return token.toJWT(keys, algorithm); + } + + public Map> construct(Map cis, CliInfo cliInfo, Map> httpArgs, + Map args) { + if (httpArgs == null) { + httpArgs = new HashMap<>(); + } + + String password = args.get("password"); + if (password == null) { + password = httpArgs.get("password").get("password"); + if (password == null) { + password = cis.get("clientSecret"); + if (password == null) { + password = cliInfo.getClientSecret(); + } + } + } + + String user = args.get("user"); + if (user == null) { + user = cliInfo.getClientId(); + } + + if (!httpArgs.keySet().contains("headers")) { + httpArgs.put("headers", null); + } + + String credentials = user + ":" + password; + String authz = Base64.encodeBase64(credentials.getBytes()); + Map hMap = httpArgs.get("headers"); + hMap.put("Authorization", "Basic " + authz); + + + cis.remove("clientSecret"); + + if (cis.get("grantType").equals("authorizationCode")) { + if (!cis.containsKey("clientId")) { + cis.put("clientId", cliInfo.getClientId()); + } + } else { + boolean req; + /* + try: + req = cis.c_param["client_id"][VREQUIRED] + except KeyError: + req = False + */ + + if (!req) { + cis.remove("clientId"); + } + } + + return httpArgs; + } +} diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java new file mode 100644 index 0000000..daeab2d --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java @@ -0,0 +1,16 @@ +package oiccli.client_auth; + +import oiccli.StringUtil; + +import java.util.Map; + +public class ClientSecretJwt extends JWSAuthenticationMethod { + + public String chooseAlgorithm(String entity, Map args) { + return JWSAuthenticationMethod.chooseAlgorithm(entity, args); + } + + public Key getSigningKey(String algorithm, CliInfo cliInfo) { + return cliInfo.keyjar.getSigningKey(StringUtil.alg2keytype(algorithm), algorithm); + } +} diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java new file mode 100644 index 0000000..9a7450e --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java @@ -0,0 +1,27 @@ +package oiccli.client_auth; + +import com.sun.security.ntlm.Client; + +import java.util.Map; + +public class ClientSecretPost extends ClientSecretBasic { + + public Map> construct(Map cis, CliInfo cliInfo, Map> httpArgs, + Map args) { + if (!cis.containsKey("clientSecret")) { + Map clientSecret = httpArgs.get("clientSecret"); + if (clientSecret != null) { + cis.put("clientSecret", clientSecret.get("clientSecret")); + httpArgs.remove("clientSecret"); + } else { + if (cliInfo.getClientSecret() != null) { + cis.put("clientSecret", cliInfo.getClientSecret()); + } + } + } + + cis.put("clientId", cliInfo.getClientId()); + + return httpArgs; + } +} diff --git a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java new file mode 100644 index 0000000..cfd7196 --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java @@ -0,0 +1,118 @@ +package oiccli.client_auth; + +import oiccli.StringUtil; +import oiccli.exceptions.AuthenticationFailure; + +import java.util.Arrays; +import java.util.HashMap; + +import oiccli.exceptions.NoMatchingKey; +import org.junit.Assert; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +public class JWSAuthenticationMethod extends ClientAuthenticationMethod { + + private static final Map DEF_SIGN_ALG = new HashMap<>() {{ + put("id_token", "RS256"); + put("userinfo", "RS256"); + put("request_object", "RS256"); + put("client_secret_jwt", "HS256"); + put("private_key_jwt", "RS256"); + }}; + private static final String JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; + + public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { + String algorithm = args.get("algorithm"); + if (algorithm == null) { + algorithm = DEF_SIGN_ALG.get(entity); + } + if (algorithm != null) { + throw new AuthenticationFailure("Missing algorithm specification"); + } + + return algorithm; + } + + public String chooseAlgorithm(Map args) throws AuthenticationFailure { + return chooseAlgorithm(null, args); + } + + public Key getSigningKey(String algorithm, CliInfo cliInfo) { + return cli_info.keyjar.get_signing_key( + StringUtil.alg2keytype(algorithm), alg = algorithm); + } + + public Key getKeyByKid(String kid, String algorithm, CliInfo cliInfo) throws NoMatchingKey { + Key key = cli_info.keyjar.get_key_by_kid(kid); + String ktype; + if (key != null) { + ktype = StringUtil.alg2keytype(algorithm); + try { + Assert.assertTrue(key.getType().equals(ktype)); + return key; + } catch (AssertionError error) { + throw new NoMatchingKey("Wrong key type"); + } + } else { + throw new NoMatchingKey("No key with kid " + kid); + } + } + + public Map construct(Map cis, CliInfo cliInfo, Map requestArgs, + Map httpArgs, Map args) throws AuthenticationFailure, NoMatchingKey { + String algorithm = null; + String audience = null; + if (args.containsKey("clientAssertion")) { + cis.put("clientAssertion", args.get("clientAssertion")); + if (args.containsKey("clientAssertionType")) { + cis.put("clientAssertionType", args.get("clientAssertionType")); + } else { + cis.put("clientAssertionType", JWT_BEARER); + } + } else if (cis.containsKey("clientAssertion")) { + if (!cis.containsKey("clientAssertionType")) { + cis.put("clientAssertionType", JWT_BEARER); + } + } else { + if (args.get("authenticationEndpoint").equals("token") || args.get("authenticationEndpoint").equals("refresh")) { + algorithm = cliInfo.registrationInfo("tokenEndpointAuthSigningAlg"); + audience = cliInfo.providerInfo("tokenEndpoint"); + } else { + audience = cliInfo.providerInfo("issuer"); + } + } + + if (algorithm == null) { + algorithm = this.chooseAlgorithm(args); + } + + String ktype = StringUtil.alg2keytype(algorithm); + List signingKey = null; + if (args.containsKey("kid")) { + signingKey = (List) Arrays.asList(this.getKeyByKid(args.get("kid"), algorithm, cliInfo)); + } else if (cliInfo.kid("sig").contains(ktype)) { + Key key = this.getKeyByKid(args.get("sig")["ktype"], algorithm, cliInfo); + if (key != null) { + signingKey = (List) Arrays.asList(key); + } else { + signingKey = this.getSigningKey(algorithm, cliInfo); + } + } + + Map hMap = new HashMap<>(); + hMap.put("lifetime", args.get("lifetime")); + + cis.put("clientAssertion", assertionJWT(cliInfo.getClientId(), signingKey, audience, algorithm, args)); + cis.put("clientAssertionType", JWT_BEARER); + cis.remove("clientSecret"); + + if (cis.cParam["clientId"][VREQUIRED]) { + cis.remove("clientId"); + } + + return new HashMap<>(); + } + +} diff --git a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java new file mode 100644 index 0000000..9fd23d1 --- /dev/null +++ b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java @@ -0,0 +1,21 @@ +package oiccli.client_auth; + +import oiccli.StringUtil; +import oiccli.exceptions.AuthenticationFailure; + +import java.util.Map; + +public class PrivateKeyJwt extends JWSAuthenticationMethod { + + public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { + return JWSAuthenticationMethod.chooseAlgorithm(entity, args); + } + + public String chooseAlgorithm(Map args) throws AuthenticationFailure { + return chooseAlgorithm("private_key_jwt", args); + } + + public Key getSigningKey(String algorithm, CliInfo cliInfo) { + return cliInfo.keyjar.getSigningKey(StringUtil.alg2keytype(algorithm), "", algorithm); + } +} diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java new file mode 100644 index 0000000..03a06df --- /dev/null +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -0,0 +1,312 @@ +package oiccli.client_info; + +import com.google.common.collect.ImmutableMap; +import com.sun.org.apache.xml.internal.security.utils.Base64; +import oiccli.StringUtil; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; + +public class ClientInfo { + + private static final Map userInfoMap = + ImmutableMap.of("sign", "userinfoSignedResponseAlg", + "alg", "userinfoEncryptedResponseAlg", + "enc", "userinfoEncryptedResponseEnc"); + private static final Map idTokenMap = + ImmutableMap.of("sign", "idTokenSignedResponseAlg", + "alg", "idTokenEncryptedResponseAlg", + "enc", "idTokenEncryptedResponseEnc"); + private static final Map requestMap = + ImmutableMap.of("sign", "requestObjectSigningAlg", + "alg", "requestObjectEncryptionAlg", + "enc", "requestObjectEncryptionEnc"); + private static final Map> attributeMap = + ImmutableMap.of("userinfo", userInfoMap, "id_token", idTokenMap, "request", requestMap); + private static final Map defSignAlg = + ImmutableMap.of("idToken", "RS256", + "userInfo", "RS256", + "requestObject", "RS256", + "clientSecretJwt", "HS256", + "privateKeyJwt", "RS256"); + + + private KeyJar keyJar; + private Database stateDb; + private List events; + private boolean shouldBeStrictOnPreferences; + private Map> providerInfo; + private Map registrationResponse; + private String registrationExpires; + private String registrationAccessToken; + private Map> kid; + private Map config; + private Map allow; + private Map> behavior; + private Map> clientPrefs; + private String baseUrl; + private String requestsDir; + private String cId; + private String cSecret; + private String issuer; + private String redirectUris; + final private static Logger logger = LoggerFactory.getLogger(ClientInfo.class); + + public ClientInfo(KeyJar keyjar, Map config, List events, + Database db, String dbName, boolean shouldBeStrictOnPreferences, + Map args) throws NoSuchFieldException, IllegalAccessException { + this.keyJar = keyjar; + this.stateDb = new State(" ", db, dbName); + this.events = events; + this.shouldBeStrictOnPreferences = shouldBeStrictOnPreferences; + this.providerInfo = new HashMap<>(); + this.registrationResponse = new HashMap<>(); + this.kid = new HashMap() {{ + put("sig", new HashMap<>()); + put("enc", new HashMap<>()); + }}; + this.config = config; + this.baseUrl = ""; + this.requestsDir = ""; + this.allow = new HashMap<>(); + this.behavior = new HashMap<>(); + this.clientPrefs = new HashMap<>(); + this.cId = ""; + this.cSecret = ""; + this.issuer = ""; + + for (String key : args.keySet()) { + this.getClass().getField(key).set(key, args.get(key)); + } + + List attributes = new ArrayList<>(Arrays.asList("clientId", "issuer", "clientSecret", "baseUrl", "requestsDir")); + String value; + for (String attribute : attributes) { + value = config.get(attribute); + if (value != null) { + this.getClass().getField(attribute).set(attribute, value); + } else { + this.getClass().getField(attribute).set(attribute, ""); + } + + if (attribute.equals("clientId")) { + this.stateDb.setClientId(config.get(attribute)); + } + } + + attributes = new ArrayList<>(Arrays.asList("allow", "clientPrefs", "behavior", "providerInfo")); + for (String attribute : attributes) { + value = config.get(attribute); + if (value != null) { + this.getClass().getField(attribute).set(attribute, value); + } else { + this.getClass().getField(attribute).set(attribute, new HashMap<>()); + } + } + + if (StringUtil.isNotNullAndNotEmpty(requestsDir)) { + File file = new File(requestsDir); + if (!file.isDirectory()) { + try { + file.mkdir(); + } catch (SecurityException se) { + logger.error("Directory " + requestsDir + " was not created"); + } + } + } + + String redirectUris = config.get("redirectUris"); + if (redirectUris != null) { + this.redirectUris = redirectUris; + } else { + this.redirectUris = null; + } + } + + public String getCSecret() { + return this.cSecret; + } + + public String getIssuer() { + return issuer; + } + + public Map> getProviderInfo() { + return providerInfo; + } + + public Map> getClientPrefs() { + return clientPrefs; + } + + public boolean getShouldBeStrictOnPreferences() { + return shouldBeStrictOnPreferences; + } + + public Map> getBehavior() { + return behavior; + } + + public void setBehavior(Map> behavior) { + this.behavior = behavior; + } + + public String getRequestsDir() { + return requestsDir; + } + + public String getClientSecret() { + return cSecret; + } + + public void setClientSecret(String cSecret) { + this.cSecret = cSecret; + } + + public void setCSecret(String secret) { + if (secret == null) { + this.cSecret = ""; + } else { + this.cSecret = secret; + if (this.keyJar == null) { + this.keyJar = new KeyJar(); + } + + this.keyjar.addSymmetric("", secret); + } + } + + //client_secret = property(get_client_secret, set_client_secret) + + public String getClientId() { + return this.cId; + } + + public void setClientId(String clientId) { + this.cId = clientId; + } + + public void setRegistrationResponse(Map registrationResponse) { + this.registrationResponse = registrationResponse; + } + + public Map getRegistrationResponse() { + return this.registrationResponse; + } + + public String getRegistrationExpires() { + return registrationExpires; + } + + public String getRegistrationAccessToken() { + return registrationAccessToken; + } + + public void setRegistrationAccessToken(String registrationAccessToken) { + this.registrationAccessToken = registrationAccessToken; + } + + public KeyJar getKeyJar() { + return keyJar; + } + + public Database getStateDb() { + return stateDb; + } + + public void setStateDb(Database stateDb) { + this.stateDb = stateDb; + } + + //client_id = property(get_client_id, set_client_id) + + public void setItem(String key, String value) throws NoSuchFieldException, IllegalAccessException { + this.getClass().getField(key).set(key, value); + } + + public String filenameFromWebname(String webName) { + Assert.assertTrue(webName.startsWith(this.baseUrl)); + webName = webName.substring(baseUrl.length()); + if (webName.startsWith("/")) { + return webName.substring(1); + } else { + return webName; + } + } + + public Map signEncAlgs(SignEncAlgs type) { + Map response = new HashMap<>(); + for (String key : attributeMap.get(type).keySet()) { + if (attributeMap.get(key) != null && this.registrationResponse.get(attributeMap.get(key)) != null) { + response.put(key, this.registrationResponse.get(attributeMap.get(key))); + } else { + if (key.equals("sign")) { + response.put(key, defSignAlg.get(type)); + } + } + } + + return response; + } + + public boolean verifyAlgSupport(String algorithm, VerifyAlgSupportUsage usage, VerifyAlgSupportType type) { + // THIS RELATES TO CLIINFO - ask Roland how to implement it + // supported = self.provider_info[ + //"{}_{}_values_supported".format(usage, typ)] + + return supported.contains(algorithm); + } + + public List generateRequestUris(String requestsDir) { + //m = hashlib.sha256() + String issuer = this.providerInfo.get("issuer"); + if (issuer != null) { + m.update(issuer.getBytes()); + } else { + m.update(this.issuer); + } + m.update(this.baseUrl.getBytes()); + + return this.baseUrl + requestsDir + "/" + m.hexDigest(); + } + + public static List addCodeChallenge(ClientInfo clientInfo) { + String codeChallengeFromMap = clientInfo.config.get("codeChallenge"); + int cvLength; + if (codeChallengeFromMap != null) { + cvLength = codeChallengeFromMap.length(); + } else { + cvLength = 64; + } + + String codeVerifier = StringUtil.generateRandomString(cvLength); + codeVerifier = Base64.encode(codeVerifier.getBytes()); + + String method = clientInfo.config['code_challenge']['method']; + if (method == null) { + method = "S256"; + } + + /* + try: + _h = CC_METHOD[_method](_cv).hexdigest() + code_challenge = b64e(_h.encode()).decode() + except KeyError: + raise Unsupported( + 'PKCE Transformation method:{}'.format(_method)) + */ + + Map hMap = new HashMap<>(); + hMap.put("codeChallenge", codeChallenge); + hMap.put("codeChallengeMethod", method); + + return Arrays.asList(hMap, codeVerifier); + } + + public void setRegistrationExpires(String registrationExpires) { + this.registrationExpires = registrationExpires; + } +} diff --git a/lib/src/main/java/oiccli/client_info/SignEncAlgs.java b/lib/src/main/java/oiccli/client_info/SignEncAlgs.java new file mode 100644 index 0000000..a29aaf2 --- /dev/null +++ b/lib/src/main/java/oiccli/client_info/SignEncAlgs.java @@ -0,0 +1,5 @@ +package oiccli.client_info; + +public enum SignEncAlgs { + ID_TOKEN, USER_INFO, REQUEST_OBJECT +} diff --git a/lib/src/main/java/oiccli/client_info/Usage.java b/lib/src/main/java/oiccli/client_info/Usage.java new file mode 100644 index 0000000..b9f329c --- /dev/null +++ b/lib/src/main/java/oiccli/client_info/Usage.java @@ -0,0 +1,5 @@ +package oiccli.client_info; + +public enum Usage { + USER_INFO, ID_TOKEN, REQUEST_OBJECT, TOKEN_ENDPOINT_AUTH; +} diff --git a/lib/src/main/java/oiccli/client_info/VerifyAlgSupportType.java b/lib/src/main/java/oiccli/client_info/VerifyAlgSupportType.java new file mode 100644 index 0000000..43e9bbc --- /dev/null +++ b/lib/src/main/java/oiccli/client_info/VerifyAlgSupportType.java @@ -0,0 +1,5 @@ +package oiccli.client_info; + +public enum VerifyAlgSupportType { + SIGNING_ALG, ENCRYPTION_ALG, ENCRYPTION_ENC; +} diff --git a/lib/src/main/java/oiccli/client_info/VerifyAlgSupportUsage.java b/lib/src/main/java/oiccli/client_info/VerifyAlgSupportUsage.java new file mode 100644 index 0000000..1d37df8 --- /dev/null +++ b/lib/src/main/java/oiccli/client_info/VerifyAlgSupportUsage.java @@ -0,0 +1,5 @@ +package oiccli.client_info; + +public enum VerifyAlgSupportUsage { + USER_INFO, ID_TOKEN, REQUEST_OBJECT, TOKEN_ENDPOINT_AUTH; +} diff --git a/lib/src/main/java/oiccli/exceptions/AESError.java b/lib/src/main/java/oiccli/exceptions/AESError.java new file mode 100644 index 0000000..84a6107 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/AESError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class AESError extends Exception{ + public AESError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java b/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java new file mode 100644 index 0000000..e5239b5 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class AuthenticationFailure extends Exception{ + public AuthenticationFailure(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/ConfigurationError.java b/lib/src/main/java/oiccli/exceptions/ConfigurationError.java new file mode 100644 index 0000000..730d2d9 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/ConfigurationError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class ConfigurationError extends Exception{ + public ConfigurationError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/ExpiredToken.java b/lib/src/main/java/oiccli/exceptions/ExpiredToken.java new file mode 100644 index 0000000..d57bfab --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/ExpiredToken.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class ExpiredToken extends Exception{ + public ExpiredToken(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java b/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java new file mode 100644 index 0000000..0a7d747 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class MissingEndpoint extends Exception{ + public MissingEndpoint(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/MissingParameter.java b/lib/src/main/java/oiccli/exceptions/MissingParameter.java new file mode 100644 index 0000000..2207c4f --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/MissingParameter.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class MissingParameter extends Exception{ + public MissingParameter(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java b/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java new file mode 100644 index 0000000..5a265bf --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class NoMatchingKey extends Exception{ + public NoMatchingKey(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/OicCliError.java b/lib/src/main/java/oiccli/exceptions/OicCliError.java new file mode 100644 index 0000000..f7a8fc5 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/OicCliError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class OicCliError extends Exception{ + public OicCliError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/ParameterError.java b/lib/src/main/java/oiccli/exceptions/ParameterError.java new file mode 100644 index 0000000..f682232 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/ParameterError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class ParameterError extends Exception { + public ParameterError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/UnsupportedType.java b/lib/src/main/java/oiccli/exceptions/UnsupportedType.java new file mode 100644 index 0000000..57d12d5 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/UnsupportedType.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class UnsupportedType extends Exception{ + public UnsupportedType(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/ValueError.java b/lib/src/main/java/oiccli/exceptions/ValueError.java new file mode 100644 index 0000000..9301f3b --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/ValueError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class ValueError extends Exception{ + public ValueError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/WrongContentType.java b/lib/src/main/java/oiccli/exceptions/WrongContentType.java new file mode 100644 index 0000000..eaeb01e --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/WrongContentType.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class WrongContentType extends Exception{ + public WrongContentType(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/service/AccessToken.java b/lib/src/main/java/oiccli/service/AccessToken.java new file mode 100644 index 0000000..740f0cd --- /dev/null +++ b/lib/src/main/java/oiccli/service/AccessToken.java @@ -0,0 +1,26 @@ +package oiccli.service; + +import oiccli.exceptions.ParameterError; + +import java.util.Arrays; +import java.util.Map; + +public class AccessToken extends service.AccessToken { + private AccessTokenRequest accessTokenRequest; + private AccessTokenResponse accessTokenResponse; + private TokenErrorResponse tokenErrorResponse; + private List<> postParseResponse; + + public AccessToken(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + this.postParseResponse = Arrays.asList(this.oicPostParseResponse); + } + + public void oicPostParseResponse(Map> response, CliInfo cliInfo, String state) throws ParameterError { + Map idt = response.get("verifiedIdToken"); + + if (!cliInfo.getStateDb().nonceToState(idt.get("nonce")).equals(state)) { + throw new ParameterError("Someone has messed with the 'nonce'"); + } + } +} diff --git a/lib/src/main/java/oiccli/service/Authorization.java b/lib/src/main/java/oiccli/service/Authorization.java new file mode 100644 index 0000000..0a5e362 --- /dev/null +++ b/lib/src/main/java/oiccli/service/Authorization.java @@ -0,0 +1,121 @@ +package oiccli.service; + +import oiccli.StringUtil; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Authorization extends service.Authorization { + + private AuthorizationRequest authorizationRequest; + private AuthorizationResponse authorizationResponse; + private AuthorizationErrorResponse authorizationErrorResponse; + private Map> defaultRequestArgs; + private List<> + + public Authorization(Object httpLib, Object keyJar, Map clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + this.defaultRequestArgs = new HashMap() {{ + put("scope", Arrays.asList("openId")); + }}; + /*self.pre_construct = [self.oic_pre_construct] + self.post_construct = [self.oic_post_construct]*/ + } + + public List> oicPreConstruct(CliInfo cliInfo, Map requestArgs, Map args) { + if (requestArgs != null) { + String responseType = requestArgs.get("responseType"); + if (responseType.contains("token") || responseType.contains("id_token")) { + if (!requestArgs.containsKey("nonce")) { + requestArgs.put("nonce", StringUtil.generateRandomString(32)); + } + } + } else { + requestArgs = new HashMap() {{ + put("nonce", StringUtil.generateRandomString(32)); + }}; + } + + Map postArgs = new HashMap<>(); + for (String attribute : Arrays.asList("requestObjectSigningAlg", "algorithm", "sigKid")) { + postArgs.put(attribute, args.get(attribute)); + args.remove(attribute); + } + + if (args.containsKey("requestMethod")) { + if (args.get("requestMethod").equals("reference")) { + postArgs.put("requestParam", "requestUri"); + } else { + postArgs.put("requestParam", "request"); + } + args.remove("requestMethod"); + } + + String responseMode = cliInfo.getBehavior("responseMode"); + if (responseMode.equals("formPost")) { + requestArgs.put("responseMode", responseMode); + } + + return Arrays.asList(requestArgs, postArgs); + } + + public Map oicPostConstruct(CliInfo cliInfo, Map req, Map args) { + String requestParam = args.get("requestParam"); + args.remove("requestParam"); + + String algorithm = null; + for (String argument : Arrays.asList("requestObjectSigningAlg", "algorithm")) { + algorithm = args.get(argument); + } + + if (algorithm == null) { + algorithm = cliInfo.getBehavior("requestObjectSigningAlg"); + if (algorithm == null) { + algorithm = "RS256"; + } + } + + args.put("requestObjectSigningAlg", algorithm); + + if (!args.containsKey("keys") && algorithm != null && !algorithm.equals("none")) { + String kty = StringUtil.alg2keytype(algorithm); + String kid = args.get("sigKid"); + if (kid == null) { + kid = cliInfo.getKid("sig").get(kty, null); + } + args.put("keys", cliInfo.getKeyJar().getSigningKey(kty, kid)); + } + + /* + _req = make_openid_request(req, **kwargs) + + # Should the request be encrypted + _req = request_object_encryption(_req, cli_info, **kwargs) + */ + + if (requestParam.equals("request")) { + req.put("request", _req); + } else { + //_webname = cli_info.registration_response['request_uris'][0] + String fileName = cliInfo.fileNameFromWebName(webname); + //except KeyError: + //filename, _webname = construct_request_uri(**kwargs) + BufferedWriter writer = null; + try { + writer = new BufferedWriter(new FileWriter(fileName)); + writer.write(_req); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + } + req.put("requestUri", _webname); + } + + return req; + } +} diff --git a/lib/src/main/java/oiccli/service/CheckID.java b/lib/src/main/java/oiccli/service/CheckID.java new file mode 100644 index 0000000..3123674 --- /dev/null +++ b/lib/src/main/java/oiccli/service/CheckID.java @@ -0,0 +1,31 @@ +package oiccli.service; + +import com.auth0.jwt.creators.Message; +import oiccli.client_info.ClientInfo; +import oiccli.service.Service; +import oiccli.service.UserInfo; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CheckID extends Service { + private static CheckIDRequest checkIDRequest; + private static Message message; + private static ErrorResponse errorResponse; + private static String endpointName = ""; + private static boolean isSynchronous = true; + private static String request = "checkSession"; + + public CheckID(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + //self.pre_construct = [self.oic_pre_construct] + } + + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); + return Arrays.asList(requestArgs, new HashMap()); + } + +} \ No newline at end of file diff --git a/lib/src/main/java/oiccli/service/CheckSession.java b/lib/src/main/java/oiccli/service/CheckSession.java new file mode 100644 index 0000000..74b6bf8 --- /dev/null +++ b/lib/src/main/java/oiccli/service/CheckSession.java @@ -0,0 +1,29 @@ +package oiccli.service; + +import com.auth0.jwt.creators.Message; +import oiccli.client_info.ClientInfo; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CheckSession extends Service { + private static CheckSessionRequest checkSessionRequest; + private static Message message; + private static ErrorResponse errorResponse; + private static String endpointName = ""; + private static boolean isSynchronous = true; + private static String request = "checkSession"; + + public CheckSession(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + //self.pre_construct = [self.oic_pre_construct] + } + + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); + return Arrays.asList(requestArgs, new HashMap()); + } + +} diff --git a/lib/src/main/java/oiccli/service/EndSession.java b/lib/src/main/java/oiccli/service/EndSession.java new file mode 100644 index 0000000..8d92250 --- /dev/null +++ b/lib/src/main/java/oiccli/service/EndSession.java @@ -0,0 +1,41 @@ +package oiccli.service; + +import com.auth0.jwt.creators.Message; +import oiccli.client_info.ClientInfo; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class EndSession extends Service { + private static EndSessionRequest endSessionRequest; + private static Message message; + private static ErrorResponse errorResponse; + private static String endpointName = "endSessionEndpoint"; + private static boolean isSynchronous = true; + private static String request = "endSession"; + + public EndSession(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib,keyJar,clientAuthenticationMethod); + //self.pre_construct = [self.oic_pre_construct] + } + + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); + return Arrays.asList(requestArgs, new HashMap()); + } + + /* + def factory(req_name, **kwargs): + for name, obj in inspect.getmembers(sys.modules[__name__]): + if inspect.isclass(obj) and issubclass(obj, oiccli.Service): + try: + if obj.__name__ == req_name: + return obj(**kwargs) + except AttributeError: + pass + + return service.factory(req_name, **kwargs) + */ +} diff --git a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java new file mode 100644 index 0000000..ed06384 --- /dev/null +++ b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java @@ -0,0 +1,125 @@ +package oiccli.service; + +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.ConfigurationError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; + +public class ProviderInfoDiscovery extends service.ProviderInfoDiscovery { + private Message message; + private ProviderConfigurationResponse providerConfigurationResponse; + private ErrorResponse errorResponse; + private final static Logger logger = LoggerFactory.getLogger(ProviderInfoDiscovery.class); + + public ProviderInfoDiscovery(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + this.postParseResponse.insert(0, this.oicPostParseResponse); + } + + public void oicPostParseResponse(String response, ClientInfo clientInfo) { + this.matchPreferences(clientInfo, response, clientInfo.getIssuer()); + } + + public static void matchPreferences(ClientInfo clientInfo, Map> pcr) throws ConfigurationError { + if (pcr == null) { + pcr = clientInfo.getProviderInfo(); + } + + RegistrationRequest rr = new oic.RegistrationRequest(); + Set set = Service.PREFERENCE2PROVIDER.entrySet(); + Iterator iterator = set.iterator(); + Map.Entry mapEntry; + String key, value; + List listOfValues, values; + while (iterator.hasNext()) { + mapEntry = (Map.Entry) iterator.next(); + key = (String) mapEntry.getKey(); + value = (String) mapEntry.getValue(); + values = clientInfo.getClientPrefs().get(key); + listOfValues = pcr.get(value); + if (listOfValues == null) { + listOfValues = Arrays.asList(Service.PROVIDERDEFAULT.get(key)); + } + if (listOfValues == null) { + logger.info("No info from provider on " + key + " and no default."); + if (clientInfo.getShouldBeStrictOnPreferences()) { + throw new ConfigurationError("OP couldn't match preferences: " + key); + } else { + listOfValues = values; + } + } + + if (listOfValues.contains(values)) { + setBehavior(clientInfo, key, values); + } else { + String vtype = rr.getCParam().get(key); + for (String valueIndex : values) { + if (listOfValues.contains(valueIndex)) { + Map> behavior = clientInfo.getBehavior(); + behavior.put(key, Arrays.asList(value)); + clientInfo.setBehavior(behavior); + } + } + } + + if (!clientInfo.getBehavior().containsKey(key)) { + throw new ConfigurationError("OP couldn't match preferences " + key); + } + } + + /* + + STARTED WITH JAVA CODE + + set = clientInfo.getClientPrefs().entrySet(); + iterator = set.iterator(); + while (iterator.hasNext()) { + mapEntry = (Map.Entry) iterator.next(); + key = (String) mapEntry.getKey(); + value = (String) mapEntry.getValue(); + + if(clientInfo.getBehavior().containsKey(key)) { + continue; + } + + value = value.g + + + } + --------------- + THIS IS THE PYTHON CODE + + for key, val in cli_info.client_prefs.items(): + if key in cli_info.behaviour: + continue + + try: + vtyp = regreq.c_param[key] + if isinstance(vtyp[0], list): + pass + elif isinstance(val, list) and not isinstance(val, + six.string_types): + val = val[0] + except KeyError: + pass + if key not in PREFERENCE2PROVIDER: + cli_info.behaviour[key] = val*/ + + logger.debug("cliInfo behavior " + clientInfo.getBehavior().toString()); + + } + + private static void setBehavior(ClientInfo clientInfo, String key, List values) { + Map> behavior = clientInfo.getBehavior(); + if (behavior.containsKey(key)) { + List returnedValue = behavior.get(key); + returnedValue.addAll(values); + behavior.put(key, returnedValue); + } else { + behavior.put(key, values); + } + clientInfo.setBehavior(behavior); + } +} diff --git a/lib/src/main/java/oiccli/service/Registration.java b/lib/src/main/java/oiccli/service/Registration.java new file mode 100644 index 0000000..4bbfe75 --- /dev/null +++ b/lib/src/main/java/oiccli/service/Registration.java @@ -0,0 +1,64 @@ +package oiccli.service; + +import oiccli.client_info.ClientInfo; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Registration extends Service { + + private RegistrationRequest registrationRequest; + private RegistrationResponse registrationResponse; + private ErrorResponse errorResponse; + private static String endpointName = "registrationEndpoint"; + private static boolean isSynchronous = true; + private static String request = "registration"; + private static String bodyType = "json"; + private static String httpMethod = "POST"; + + public Registration(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + /* + self.pre_construct = [self.oic_pre_construct] + self.post_parse_response.append(self.oic_post_parse_response) + */ + } + + public List>> oicPreConstruct(ClientInfo clientInfo, Map> requestArgs) { + for (String key : this.registrationRequest.getCParam().keySet()) { + if (!requestArgs.containsKey(key)) { + requestArgs.put(key, clientInfo.getBehavior().get(key)); + } + } + + if (!requestArgs.containsKey("postLogoutRedirectUris")) { + requestArgs.put("postLogoutRedirectUris", clientInfo.getPostLogoutRedirectUris()); + } + + if (!requestArgs.containsKey("redirectUris")) { + requestArgs.put("redirectUris", clientInfo.getRedirectUris()); + } + + if (clientInfo.getProviderInfo().get("requireRequestUriRegistration")) { + requestArgs.put("requestUris", clientInfo.generateRequestUris(clientInfo.getRequestsDir())); + } + + return Arrays.asList(requestArgs, new HashMap>()); + } + + public void oicPostParseResponse(Map response, ClientInfo cliInfo) { + cliInfo.setRegistrationResponse(response); + if (!cliInfo.getRegistrationResponse().containsKey("tokenEndpointAuthMethod")) { + Map hMap = cliInfo.getRegistrationResponse(); + hMap.put("tokenEndpointAuthMethod", "clientSecretBasic"); + cliInfo.setRegistrationResponse(hMap); + } + + cliInfo.setClientId(response.get("clientId")); + cliInfo.setClientSecret(response.get("clientSecret")); + cliInfo.setRegistrationExpires(response.get("clientSecretExpiresAt")); + cliInfo.setRegistrationAccessToken(response.get("registrationAccessToken")); + } +} diff --git a/lib/src/main/java/oiccli/service/Service.java b/lib/src/main/java/oiccli/service/Service.java new file mode 100644 index 0000000..f151656 --- /dev/null +++ b/lib/src/main/java/oiccli/service/Service.java @@ -0,0 +1,37 @@ +package oiccli.service; + +import javax.management.ImmutableDescriptor; +import java.util.HashMap; +import java.util.Map; + +public class Service { + + public static final Map PREFERENCE2PROVIDER = + new HashMap() {{ + put("request_object_signing_alg", "request_object_signing_alg_values_supported"); + put("request_object_encryption_alg", "request_object_encryption_alg_values_supported"); + put("request_object_encryption_enc", "request_object_encryption_enc_values_supported"); + put("userinfo_signed_response_alg", "userinfo_signing_alg_values_supported"); + put("userinfo_encrypted_response_alg", "userinfo_encryption_alg_values_supported"); + put("userinfo_encrypted_response_enc", "userinfo_encryption_enc_values_supported"); + put("id_token_signed_response_alg", "id_token_signing_alg_values_supported"); + put("id_token_encrypted_response_alg", "id_token_encryption_alg_values_supported"); + put("id_token_encrypted_response_enc", "id_token_encryption_enc_values_supported"); + put("default_acr_values", "acr_values_supported"); + put("subject_type", "subject_types_supported"); + put("token_endpoint_auth_method", "token_endpoint_auth_methods_supported"); + put("token_endpoint_auth_signing_alg", "token_endpoint_auth_signing_alg_values_supported"); + put("response_types", "response_types_supported"); + put("grant_types", "grant_types_supported"); + }}; + + public static final Map PROVIDERDEFAULT = + new HashMap() {{ + put("token_endpoint_auth_method", "client_secret_basic"); + put("id_token_signed_response_alg", "RS256"); + }}; + + + public Service(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + } +} diff --git a/lib/src/main/java/oiccli/service/UserInfo.java b/lib/src/main/java/oiccli/service/UserInfo.java new file mode 100644 index 0000000..a7d8c27 --- /dev/null +++ b/lib/src/main/java/oiccli/service/UserInfo.java @@ -0,0 +1,162 @@ +package oiccli.service; + +import com.auth0.jwt.creators.Message; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; + +import java.util.*; + +public class UserInfo extends Service { + private Message message; + private OpenIDSchema openIDSchema; + private UserInfoErrorResponse userInfoErrorResponse; + private static String endpointName = "userInfoEndpoint"; + private static boolean isSynchronous = true; + private String request = "userInfo"; + private String defaultAuthenticationMethod = "bearerHeader"; + private String httpMethod = "POST"; + + public UserInfo(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { + super(httpLib, keyJar, clientAuthenticationMethod); + /* + self.pre_construct = [self.oic_pre_construct] + self.post_parse_response.insert(0, self.oic_post_parse_response) + */ + } + + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + if (!requestArgs.containsKey("accessToken")) { + //_tinfo = cli_info.state_db.get_token_info(**kwargs) + requestArgs.put("accessToken", tInfo.get("accessToken")); + } + + return Arrays.asList(requestArgs, new HashMap()); + } + + /* + def oic_post_parse_response(self, resp, client_info, **kwargs): + resp = self.unpack_aggregated_claims(resp, client_info) + return self.fetch_distributed_claims(resp, client_info) + */ + + public Map> unpackAggregatedClaims(Map> userInfo, ClientInfo clientInfo) { + Map csrc = userInfo.get("claimSources"); + Set set = csrc.entrySet(); + Iterator iterator = set.iterator(); + Map.Entry mapEntry, mapEntryInner; + String key, keyInner; + Map value, valueInner; + while (iterator.hasNext()) { + mapEntry = (Map.Entry) iterator.next(); + key = (String) mapEntry.getKey(); + value = (Map) mapEntry.getValue(); + if (value.containsKey("JWT")) { + Map aggregatedClaims = new Message().fromJWT(value.get("JWT"), clientInfo.getKeyJar()); + Map cName = userInfo.get("claimNames"); + set = cName.entrySet(); + iterator = set.iterator(); + List claims = new ArrayList<>(); + while (iterator.hasNext()) { + mapEntryInner = (Map.Entry) iterator.next(); + keyInner = (String) mapEntryInner.getKey(); + valueInner = (Map) mapEntryInner.getValue(); + /*if(valueInner) + + + */ + } + } + } + + return userInfo; + } + + public Map> fetchDistributedClaims(Map> userInfo, ClientInfo clientInfo, Object callBack) { + Map csrc = userInfo.get("claimSources"); + Set set = csrc.entrySet(); + Iterator iterator = set.iterator(); + Map.Entry mapEntry, mapEntryInner; + String key, keyInner; + Map value, valueInner; + while (iterator.hasNext()) { + mapEntry = (Map.Entry) iterator.next(); + key = (String) mapEntry.getKey(); + value = (Map) mapEntry.getValue(); + if (value.containsKey("endpoint")) { + if (value.containsKey("accessToken")) { + /* + _uinfo = self.service_request( + spec["endpoint"], method='GET', + token=spec["access_token"], client_info=cli_info) + */ + } else { + if (callBack != null) { + /*_uinfo = self.service_request( + spec["endpoint"], + method='GET', + token=callback(spec['endpoint']), + client_info=cli_info)*/ + } else { + /* + _uinfo = self.service_request( + spec["endpoint"], + method='GET', + client_info=cli_info) + */ + } + } + + /* + claims = [value for value, src in + userinfo["_claim_names"].items() if src == csrc] + */ + + + } + } + } + + public static Map setIdToken(ClientInfo cliInfo, Map requestArgs, Map args) { + if (requestArgs == null) { + requestArgs = new HashMap<>(); + } + + String property = args.get("prop"); + if (property == null) { + property = "idToken"; + } + + if (!requestArgs.containsKey(property)) { + String idToken; + try { + String state = getState(requestArgs, args); + idToken = cliInfo.getStateDb().getIdToken(state); + if (idToken == null) { + throw new MissingParameter("No valid id token available"); + } + requestArgs.put(property, idToken); + } catch (MissingParameter missingParameter) { + missingParameter.printStackTrace(); + } + } + + return requestArgs; + } + + public static String getState(Map requestArgs, Map args) throws MissingParameter { + String state = args.get("state"); + if (state == null) { + state = requestArgs.get("state"); + if (state == null) { + throw new MissingParameter("state"); + } + } + + return state; + } + +} From 45c3786056f2f1924e8ad34b84f25ff47c1abf75 Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Fri, 12 Jan 2018 14:56:46 -0800 Subject: [PATCH 03/10] Oicclient --- lib/src/main/java/oiccli/Tuple.java | 20 +++ .../oiccli/exceptions/WebFingerError.java | 7 + lib/src/main/java/oiccli/webfinger/Base.java | 94 +++++++++++ lib/src/main/java/oiccli/webfinger/JRD.java | 48 ++++++ .../java/oiccli/webfinger/URINormalizer.java | 50 ++++++ .../main/java/oiccli/webfinger/WebFinger.java | 150 ++++++++++++++++++ 6 files changed, 369 insertions(+) create mode 100644 lib/src/main/java/oiccli/Tuple.java create mode 100644 lib/src/main/java/oiccli/exceptions/WebFingerError.java create mode 100644 lib/src/main/java/oiccli/webfinger/Base.java create mode 100644 lib/src/main/java/oiccli/webfinger/JRD.java create mode 100644 lib/src/main/java/oiccli/webfinger/URINormalizer.java create mode 100644 lib/src/main/java/oiccli/webfinger/WebFinger.java diff --git a/lib/src/main/java/oiccli/Tuple.java b/lib/src/main/java/oiccli/Tuple.java new file mode 100644 index 0000000..10bf39f --- /dev/null +++ b/lib/src/main/java/oiccli/Tuple.java @@ -0,0 +1,20 @@ +package oiccli; + +public class Tuple { + + public final String a; + public final String b; + + public Tuple(String a, String b) { + this.a = a; + this.b = b; + } + + public String getA() { + return a; + } + + public String getB() { + return b; + } +} diff --git a/lib/src/main/java/oiccli/exceptions/WebFingerError.java b/lib/src/main/java/oiccli/exceptions/WebFingerError.java new file mode 100644 index 0000000..768f1ba --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/WebFingerError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class WebFingerError extends Exception{ + public WebFingerError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/webfinger/Base.java b/lib/src/main/java/oiccli/webfinger/Base.java new file mode 100644 index 0000000..557c361 --- /dev/null +++ b/lib/src/main/java/oiccli/webfinger/Base.java @@ -0,0 +1,94 @@ +package oiccli.webfinger; + +import oiccli.exceptions.ValueError; +import org.junit.Assert; + +import java.util.*; + +public class Base { + + private Map ava; + private Map>> cParams; + static final Map link = new HashMap() {{ + put("rel", new HashMap() {{ put("type", String.class); put("required", true); }}); + put("type", new HashMap() {{ put("type", String.class); put("required", false); }}); + put("href", new HashMap() {{ put("type", String.class); put("required", false); }}); + put("titles", new HashMap() {{ put("type", Map.class); put("required", false); }}); + put("properties", new HashMap() {{ put("type", Map.class); put("required", false); }}); + }}; + + public Base(Map hMap) { + ava = new HashMap<>(); + if(hMap != null) { + this.load(hMap); + } + cParams = new HashMap<>(); + } + + public void setItem(String key, List value) { + HashMap> spec = this.cParams.get(key); + if(spec == null) { + spec = new HashMap>() {{ + put("type", Arrays.asList(this.toString())); + put("isRequired", Arrays.asList(false)); + }}; + } + + List types = spec.get("type"); + Object t1, t2; + if(types != null && types.size() == 2) { + t1 = types.get(0); + t2 = types.get(1); + } else { + throw new IllegalArgumentException("'Type' should have returned 2 values"); + } + + if(t1.getClass().equals(List.class)) { + List result = new ArrayList<>(); + if(t2.equals(link)) { + for(String index : value) { + result.add(link.get(index)); + } + } else { + for(String index : value) { + Assert.assertTrue(index instanceof t2); + result.add(index); + } + } + ava.put(key, result); + } + } + + public void load(Map> hMap) throws ValueError { + for(String key : this.cParams.keySet()) { + if(!hMap.containsKey(key) && cParams.get(key).get("required")) { + throw new ValueError("Required attribute " + key + " missing"); + } + } + + for(String key : hMap.keySet()) { + if(!hMap.get(key).equals("") || !hMap.get(key).isEmpty()) { + setItem(key, hMap.get(key)); + } + } + } + + public Map> dump() { + Map> result = new HashMap<>(); + List list = new ArrayList<>(); + for(String key : this.ava.keySet()) { + list = this.cParams.get(key).get("type"); + + if (list != null && list.size() == 2 && (list.get(0) instanceof List) && (list.get(1) instanceof Map)) { + List sRes = new ArrayList(list); + for (Base index : list) { + sRes.add(index.dump()); + } + list = sRes; + } + result.put(key, this.cParams.get(key)); + } + + return result; + } +} diff --git a/lib/src/main/java/oiccli/webfinger/JRD.java b/lib/src/main/java/oiccli/webfinger/JRD.java new file mode 100644 index 0000000..f09cb69 --- /dev/null +++ b/lib/src/main/java/oiccli/webfinger/JRD.java @@ -0,0 +1,48 @@ +package oiccli.webfinger; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class JRD extends Base{ + private static final Map cParam = new HashMap() {{ + put("expires", new HashMap() {{ put("type", String.class); put("required", false); }}); + put("subject", new HashMap() {{ put("type", String.class); put("required", false); }}); + put("aliases", new HashMap() {{ put("type", Arrays.asList(String.class, List.class)); put("required", false); }}); + put("properties", new HashMap() {{ put("type", Map.class); put("required", false); }}); + put("links", new HashMap() {{ put("type", Arrays.asList(List.class, Map.class)); put("required", false); }}); + }}; + private int expDays; + private int expSeconds; + private int expMins; + private int expHour; + private int expWeek; + + public JRD(Map hMap, int days, int seconds, int minutes, int hours, int weeks) { + super(hMap); + this.expiresIn(days, seconds, minutes, hours, weeks); + } + + public JRD() { + this(null,0,0,0,0,0); + } + + public void expiresIn(int days, int seconds, int minutes, int hours, int weeks) { + this.expDays = days; + this.expSeconds = seconds; + this.expMins = minutes; + this.expHour = hours; + this.expWeek = weeks; + } + + public Map> export() { + Map> result = dump(); + result.put("expires", inAWhile(this.expDays, this.expSeconds, this.expMins, this.expHour, this.expWeek)); + return result; + } + + public Map getcParam() { + return cParam; + } +} diff --git a/lib/src/main/java/oiccli/webfinger/URINormalizer.java b/lib/src/main/java/oiccli/webfinger/URINormalizer.java new file mode 100644 index 0000000..9f8c13c --- /dev/null +++ b/lib/src/main/java/oiccli/webfinger/URINormalizer.java @@ -0,0 +1,50 @@ +package oiccli.webfinger; + +import org.junit.Assert; + +public class URINormalizer { + + public boolean hasScheme(String path) { + if(path.contains("://")) { + return true; + } else { + String authority = path.replace("/", "#") + .replace("?", "#").split("#")[0]; + + String hostOrPort; + if(authority.contains(":")) { + hostOrPort = authority.split(":", 1)[1]; + if(hostOrPort.matches("^\\d+$")) { + return false; + } + } else { + return false; + } + } + + return true; + } + + public boolean isAccountSchemeAssumed(String path) { + String[] arr; + if(path.contains("@")) { + arr = path.split("@"); + String host = arr[arr.length-1]; + return !(host.contains(":") || host.contains("/") || host.contains("?")); + } else { + return false; + } + } + + public String normalize(String path) { + if(!this.hasScheme(path)) { + if(this.isAccountSchemeAssumed(path)) { + path = "acct:" + path; + } else { + path = "https://" + path; + } + } + + return path.split("#")[0]; + } +} diff --git a/lib/src/main/java/oiccli/webfinger/WebFinger.java b/lib/src/main/java/oiccli/webfinger/WebFinger.java new file mode 100644 index 0000000..7be97d1 --- /dev/null +++ b/lib/src/main/java/oiccli/webfinger/WebFinger.java @@ -0,0 +1,150 @@ +package oiccli.webfinger; + +import com.google.common.base.Strings; +import com.sun.deploy.net.HttpResponse; +import oiccli.HTTP.Response; +import oiccli.Tuple; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.WebFingerError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.util.*; + +public class WebFinger { + + public String defaultRelt; + public Object httpd; + private JRD jrd; + private List> events; + private static final String WF_URL = "https://%s/.well-known/webfinger"; + final private static Logger logger = LoggerFactory.getLogger(WebFinger.class); + private static final String OIC_ISSUER = "http://openid.net/specs/connect/1.0/issuer"; + + public WebFinger(String defaultRelt, Object httpd) { + this.defaultRelt = defaultRelt; + this.httpd = httpd; + this.jrd = null; + this.events = new ArrayList<>(); + } + + public String query(String resource, List rel) throws URISyntaxException, WebFingerError { + resource = new URINormalizer().normalize(resource); + List queryParamsTuple = new ArrayList<>(); + queryParamsTuple.add(new Tuple("resource", resource)); + + if(rel == null) { + if(this.defaultRelt != null) { + queryParamsTuple.add(new Tuple("rel", this.defaultRelt)); + } + } else { + for(String index : rel) { + queryParamsTuple.add(new Tuple("rel", index)); + } + } + + String host; + if(resource.startsWith("http")) { + URI uri = new URI(resource); + host = uri.getHost(); + int port = uri.getPort(); + if(port != -1) { + host += ":" + port; + } + } else if(resource.startsWith("acct:")) { + String[] arr = resource.split("@"); + host = arr[arr.length-1]; + arr = host.replace("/", "#").replace("?", "#").split("#"); + host = arr[0]; + } else if(resource.startsWith("device:")) { + String[] arr = resource.split(":"); + host = arr[1]; + } else { + throw new WebFingerError("Unknown schema"); + } + + String queryParams = ""; + for(int i = 0; i < queryParamsTuple.size(); i++) { + queryParams += queryParamsTuple.get(i).getA() + "=" + queryParamsTuple.get(i).getB(); + if(i != queryParamsTuple.size()-1) { + queryParams += "&"; + } + } + + return String.format(WF_URL, host) + "?" + URLEncoder.encode(queryParams); + } + + public static JRD load(Map item) { + return new JRD(json.loads(item)); + } + + public Map> httpArgs(JRD jrd) { + if(jrd == null) { + if(this.jrd != null) { + jrd = this.jrd; + } else { + return null; + } + } + + Map hMap = new HashMap() {{ + put("Access-Control-Allow-Origin", "*"); + put("Content-Type", "application/json; charset=UTF-8"); + }}; + + Map> headersAndBody = new HashMap<>(); + headersAndBody.put("headers", hMap); + headersAndBody.put("body", json.dumps(jrd.export())); + + return headersAndBody; + } + + public String discoveryQuery(String resource) throws URISyntaxException, WebFingerError { + logger.debug("Looking for OIDC OP for '" + resource + "'"); + String url = this.query(resource, Arrays.asList(OIC_ISSUER)); + HttpResponse response = this.httpd(url, true); + int statusCode = response.getStatusCode(); + Map hMap = new HashMap<>(); + if(statusCode == 200) { + if(this.events != null) { + hMap.put("Response", response.getResponseHeader()); + this.events.add(hMap); + } + + this.jrd = load(response.getResponseHeader()); + if(this.events != null) { + hMap = new HashMap<>(); + hMap.put("JRD Response", this.jrd); + this.events.add(hMap); + } + for(Object link : this.jrd.getcParam().get("links")) { + if(link.getRel().equals(OIC_ISSUER)) { + if(!link.getHRef().startsWith("https://")) { + throw new WebFingerError("Must be a HTTPS href"); + } + return link.getHRef(); + } + } + return null; + } else if(statusCode == 301 || statusCode == 302 || statusCode == 307) { + return this.discoveryQuery(response.getResponseHeader("location")); + } else { + throw new WebFingerError("Status code is: " + statusCode); + } + } + + public String response(String subject, String base, Map args) throws NoSuchFieldException, IllegalAccessException { + this.jrd = new JRD(); + this.jrd.setSubject(subject); + Base.link.put("rel", OIC_ISSUER); + Base.link.put("href", base); + this.jrd.setLinks(Arrays.asList(Base.link)); + for(String key : args.keySet()) { + this.jrd.getClass().getField(key).set(key, args.get(key)); + } + return json.dumps(this.jrd.export()); + } +} From d075a2dd78a84f40b6c6908500260a156075042b Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Tue, 23 Jan 2018 13:57:19 -0800 Subject: [PATCH 04/10] Oicclient --- .../java/oiccli/AuthorizationResponse.java | 106 +++++++++++++ lib/src/main/java/oiccli/Service.java | 150 +++++++++++------- lib/src/main/java/oiccli/State.java | 47 +++++- lib/src/main/java/oiccli/Util.java | 33 ++-- .../java/oiccli/client_auth/BearerBody.java | 23 ++- .../java/oiccli/client_auth/BearerHeader.java | 19 +-- .../oiccli/client_auth/ClientSecretBasic.java | 19 +-- .../oiccli/client_auth/ClientSecretJwt.java | 9 +- .../client_auth/JWSAuthenticationMethod.java | 44 ++--- .../oiccli/client_auth/PrivateKeyJwt.java | 6 +- .../java/oiccli/client_info/ClientInfo.java | 82 +++++++--- .../java/oiccli/exceptions/AtHashError.java | 7 + .../java/oiccli/exceptions/CHashError.java | 7 + .../oiccli/exceptions/MessageException.java | 7 + .../exceptions/MissingRequiredAttribute.java | 7 + .../java/oiccli/exceptions/OicMsgError.java | 7 + .../java/oiccli/exceptions/UnknownState.java | 7 + .../main/java/oiccli/service/AccessToken.java | 6 +- .../java/oiccli/service/Authorization.java | 31 ++-- lib/src/main/java/oiccli/service/CheckID.java | 3 +- .../java/oiccli/service/CheckSession.java | 3 +- .../main/java/oiccli/service/EndSession.java | 3 +- .../oiccli/service/ProviderInfoDiscovery.java | 61 ++++--- .../main/java/oiccli/service/UserInfo.java | 88 +++++----- lib/src/main/java/oiccli/webfinger/Base.java | 1 + .../main/java/oiccli/webfinger/WebFinger.java | 59 ++++++- 26 files changed, 588 insertions(+), 247 deletions(-) create mode 100644 lib/src/main/java/oiccli/AuthorizationResponse.java create mode 100644 lib/src/main/java/oiccli/exceptions/AtHashError.java create mode 100644 lib/src/main/java/oiccli/exceptions/CHashError.java create mode 100644 lib/src/main/java/oiccli/exceptions/MessageException.java create mode 100644 lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java create mode 100644 lib/src/main/java/oiccli/exceptions/OicMsgError.java create mode 100644 lib/src/main/java/oiccli/exceptions/UnknownState.java diff --git a/lib/src/main/java/oiccli/AuthorizationResponse.java b/lib/src/main/java/oiccli/AuthorizationResponse.java new file mode 100644 index 0000000..da75109 --- /dev/null +++ b/lib/src/main/java/oiccli/AuthorizationResponse.java @@ -0,0 +1,106 @@ +package oiccli; + +import oiccli.exceptions.AtHashError; +import oiccli.exceptions.CHashError; +import oiccli.exceptions.MissingRequiredAttribute; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class AuthorizationResponse { + + private String code; + private String accessToken; + private String tokenType; + private String idToken; + + public AuthorizationResponse() { + + } + + public boolean verify(Map args) throws MissingRequiredAttribute { + //super(AuthorizationResponse, self).verify(**kwargs) + + if(this.contains("aud")) { + if(args.containsKey("clientId")) { + if(!this.getAudience().contains(args.get("clientId"))) { + return false; + } + } + } + + if(this.contains("idToken")) { + Map argsTemp = new HashMap<>(); + for(String arg : Arrays.asList("key", "keyjar", "algs", "sender")) { + argsTemp.put(arg, args.get(arg)); + } + + /* + idt = IdToken().from_jwt(str(self["id_token"]), **args) + if not idt.verify(**kwargs): + raise VerificationError("Could not verify id_token", idt) + + _alg = idt.jws_header["alg"] + */ + + String hFunction = "HS" + algorithm.substring(0,algorithm.length()-3); + if(this.getAccessToken() != null) { + if(this.idt.getAtHash() == null) { + throw new MissingRequiredAttribute("Missing at_hash property" + + idToken.toString()); + } + + if(idt.getAtHash() != jws.leftHash(this.getAccessToken(), hFunction)) { + throw new AtHashError( + "Failed to verify access_token hash " + idt.toString()); + } + } + + if(this.getCode() != null) { + if(this.idt.getCHash() == null) { + throw new MissingRequiredAttribute("Missing cHash property" + + idToken.toString()); + } + if(idt.getCHash() != jws.leftHash(this.getCode(), hFunction)) { + throw new CHashError("Failed to verify code hash " + idt.toString()); + } + } + + this.setVerifiedIdToken(idt); + } + return true; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getTokenType() { + return tokenType; + } + + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } + + public String getIdToken() { + return idToken; + } + + public void setIdToken(String idToken) { + this.idToken = idToken; + } +} diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java index e505a0f..668e0c8 100644 --- a/lib/src/main/java/oiccli/Service.java +++ b/lib/src/main/java/oiccli/Service.java @@ -3,9 +3,7 @@ import com.auth0.jwt.creators.Message; import oiccli.HTTP.Response; import oiccli.client_info.ClientInfo; -import oiccli.exceptions.MissingEndpoint; -import oiccli.exceptions.OicCliError; -import oiccli.exceptions.UnsupportedType; +import oiccli.exceptions.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,14 +43,14 @@ public class Service { private Message msgType; private Message responseCls; private ErrorResponse errorResponse; - private String endpointName = ""; + private String endpointName; private boolean isSynchronous = true; - private String request = ""; - private String defaultAuthenticationMethod = ""; - private String httpMethod = "GET"; - private String bodyType = "urlencoded"; - private String responseBodyType = "json"; - private String endpoint = ""; + private String request; + private String defaultAuthenticationMethod; + private String httpMethod; + private String bodyType; + private String responseBodyType; + private String endpoint; private String httpLib; private KeyJar keyJar; private String clientAuthenticationMethod; @@ -73,9 +71,42 @@ public Service(String httpLib, KeyJar keyJar, String clientAuthenticationMethod, this.preConstruct = new ArrayList<>(); this.postConstruct = new ArrayList<>(); this.postParseResponse = new ArrayList<>(); + this.httpMethod = "GET"; + this.bodyType = "urlencoded"; + this.responseBodyType = "json"; + this.defaultAuthenticationMethod = ""; + this.request = ""; + this.endpoint = ""; + this.endpointName = ""; this.setUp(); } + public void gatherRequestArgs(ClientInfo clientInfo, Map args) { + + } + + public static Map> updateHttpArgs(Map httpArgs, Map> info) { + Map hArgs = info.get("hArgs"); + if (hArgs == null) { + hArgs = new HashMap<>(); + } + + if (httpArgs == null) { + httpArgs = hArgs; + } else { + httpArgs.update(info.get("hArgs")); + } + + final String headers = info.get("kwargs").get("headers"); + Map hMap = new HashMap() {{ + put("headers", headers); + }}; + httpArgs.update(hMap); + + info.put("httpArgs", httpArgs); + return info; + } + public Map parseArgs(ClientInfo clientInfo, Map args) throws NoSuchFieldException, IllegalAccessException { Map arArgs = new HashMap<>(args); Object value; @@ -126,7 +157,7 @@ public Message constructMessage(ClientInfo clientInfo, Map reque args.remove("state"); } - Map argsParam = this.parseArgs(clientInfo, requestArgs); + Map argsParam = this.gatherRequestArgs(clientInfo, requestArgs); this.msgType(argsParam); return this.doPostConstruct(clientInfo, requestArgs, returnedArgs.get(1)); @@ -135,36 +166,33 @@ public Message constructMessage(ClientInfo clientInfo, Map reque public String getEndpoint(Map args) throws MissingEndpoint { String uri = args.get("endpoint"); - if (uri == null) { - uri = this.endpoint; - } - - if (uri == null || uri.isEmpty()) { - throw new MissingEndpoint("No endpoint specified"); + if (uri != null) { + args.remove("endpoint"); + } else { + if (StringUtil.isNotNullAndNotEmpty(this.endpoint)) { + uri = this.endpoint; + } else { + throw new MissingEndpoint("No endpoint specified"); + } } return uri; } - public Map uriAndBody(Message cis, String method, Map requestArgs, Map args) throws UnsupportedEncodingException, UnsupportedType { - Map response = null; - try { - String uri = this.getEndpoint(requestArgs); - response = Util.getOrPost(uri, method, cis, args); - response.put("cis", cis); - Map hMap = new HashMap<>(); - hMap.put("headers", response.get("headers")); - response.put("h_args", hMap); - } catch (MissingEndpoint missingEndpoint) { - missingEndpoint.printStackTrace(); - } + public Map uriAndBody(Message cis, String method, Map args) throws UnsupportedEncodingException, UnsupportedType, MissingEndpoint { + String uri = this.getEndpoint(args); + Map response = Util.getOrPost(uri, method, cis, args); + response.put("cis", cis); + Map hMap = new HashMap<>(); + hMap.put("headers", response.get("headers")); + response.put("hArgs", hMap); return response; } public Map initAuthenticationMethod(Message cis, ClientInfo clientInfo, String authenticationMethod, - Map requestArgs, Map args) { - return initAuthenticationMethod(cis, clientInfo, authenticationMethod, requestArgs, null, args); + Map httpArgs, Map args) { + return initAuthenticationMethod(cis, clientInfo, authenticationMethod, httpArgs, null, args); } public Map initAuthenticationMethod(Message cis, ClientInfo clientInfo, String authenticationMethod, @@ -173,11 +201,7 @@ public Map initAuthenticationMethod(Message cis, ClientInfo clie httpArgs = new HashMap<>(); } - if (requestArgs == null) { - requestArgs = new HashMap<>(); - } - - if (authenticationMethod != null) { + if (StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { //return this.client_authn_method[authn_method]().construct( // cis, cli_info, request_args, http_args, **kwargs); } else { @@ -185,8 +209,8 @@ public Map initAuthenticationMethod(Message cis, ClientInfo clie } } - public ClientInfo requestInfo(ClientInfo clientInfo, String method, Map requestArgs, - String bodyType, String authenticationMethod, boolean lax, Map args) throws NoSuchFieldException, IllegalAccessException { + public Map requestInfo(ClientInfo clientInfo, String method, Map requestArgs, + String bodyType, String authenticationMethod, boolean lax, Map args) throws NoSuchFieldException, IllegalAccessException, MissingEndpoint, UnsupportedEncodingException, UnsupportedType { if (method == null) { method = this.httpMethod; } @@ -210,7 +234,7 @@ public ClientInfo requestInfo(ClientInfo clientInfo, String method, Map hArg = new HashMap<>(); - if (authenticationMethod != null) { + if (StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { hArg = this.initAuthenticationMethod(cis, clientInfo, authenticationMethod, requestArgs, args); } @@ -226,10 +250,10 @@ public ClientInfo requestInfo(ClientInfo clientInfo, String method, Map httpArgs, ClientInfo info) { + public Map updateHttpArgs(Map httpArgs, Map info) { Map hArgs = info.get("hArgs"); if (hArgs == null) { hArgs = new HashMap<>(); @@ -245,19 +269,19 @@ public ClientInfo updateHttpArgs(Map httpArgs, ClientInfo info) return info; } - public ClientInfo doRequestInit(ClientInfo clientInfo, String bodyType, String method, String authenticationMethod, - Map requestArgs, Map httpArgs, Map args) throws NoSuchFieldException, IllegalAccessException { - if (method == null || method.isEmpty()) { + public Map doRequestInit(ClientInfo clientInfo, String bodyType, String method, String authenticationMethod, + Map requestArgs, Map httpArgs, Map args) throws NoSuchFieldException, IllegalAccessException, MissingEndpoint, UnsupportedEncodingException, UnsupportedType { + if (!StringUtil.isNotNullAndNotEmpty(method)) { method = this.httpMethod; } - if (authenticationMethod == null || authenticationMethod.isEmpty()) { + if (!StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { authenticationMethod = this.defaultAuthenticationMethod; } - if (bodyType == null || bodyType.isEmpty()) { + if (!StringUtil.isNotNullAndNotEmpty(bodyType)) { bodyType = this.bodyType; } - ClientInfo info = this.requestInfo(clientInfo, method, requestArgs, bodyType, authenticationMethod, false, args); + Map info = this.requestInfo(clientInfo, method, requestArgs, bodyType, authenticationMethod, false, args); return this.updateHttpArgs(httpArgs, info); } @@ -271,12 +295,10 @@ public String getUrlInfo(String info) throws URISyntaxException { } if (StringUtil.isNotNullAndNotEmpty(query)) { - info = query; + return query; } else { - info = fragment; + return fragment; } - - return info; } public Message parseResponse(String info, ClientInfo clientInfo, String sFormat, String state, @@ -351,21 +373,21 @@ public ErrorResponse parseErrorMessage(Response response, String bodyType) { bodyTypeResult = bodyType; } - ErrorResponse errorResponse = this.errorResponse.deserialize(response.getText(), bodyType); + ErrorResponse errorResponse = this.errorResponse.deserialize(response.getText(), bodyTypeResult); errorResponse.verify(); return errorResponse; } - public String getValueType(Response response, String bodyType) { + public String getValueType(FakeResponse response, String bodyType) throws WrongContentType, ValueError { if (StringUtil.isNotNullAndNotEmpty(bodyType)) { - return this.verifyHeader(response, bodyType); + return Util.verifyHeader(response, bodyType); } else { return "urlencoded"; } } - public ErrorResponse parseRequestResponse(Response response, ClientInfo clientInfo, String responseBodyType, + public ErrorResponse parseRequestResponse(ErrorResponse response, ClientInfo clientInfo, String responseBodyType, String state, Map args) { int statusCode = response.getStatusCode(); if (successfulCodes.contains(statusCode)) { @@ -388,8 +410,8 @@ public ErrorResponse parseRequestResponse(Response response, ClientInfo clientIn } } - public ErrorResponse serviceRequest(String url, String method, String body, String responseBodyType, Map httpArgs, - ClientInfo clientInfo, Map args) { + public static ErrorResponse serviceRequest(String url, String method, String body, String responseBodyType, Map httpArgs, + ClientInfo clientInfo, Map args) { if (httpArgs == null) { httpArgs = new HashMap<>(); } @@ -404,6 +426,18 @@ public ErrorResponse serviceRequest(String url, String method, String body, Stri responseBodyType = this.responseBodyType; } - return this.parseRequestResponse(response, clientInfo, responseBodyType, "", args); + return parseRequestResponse(response, clientInfo, responseBodyType, "", args); + } + + public static ErrorResponse serviceRequest(String url, Map args) { + return serviceRequest(url, "GET", null, "", null, null, args); + } + + public static ErrorResponse serviceRequest(String url, String method, ClientInfo clientInfo, Map args) { + return serviceRequest(url, "GET", null, "", null, null, args); + } + + public static ErrorResponse serviceRequest(String url, String method, ClientInfo clientInfo) { + return serviceRequest(url, "GET", null, "", null, null, null); } } diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java index dda8715..0e70810 100644 --- a/lib/src/main/java/oiccli/State.java +++ b/lib/src/main/java/oiccli/State.java @@ -1,7 +1,10 @@ package oiccli; import oiccli.exceptions.ExpiredToken; +import oiccli.exceptions.UnknownState; +import sun.swing.plaf.synth.DefaultSynthStyle; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -25,6 +28,10 @@ public State(String clientId, Database db, String dbName, int lifetime) { this.lifetime = lifetime; } + public State(String clientId, Database db, String dbName) { + this(clientId, db, dbName, 600); + } + public String createState(final String receiver, Object request) { String state = StringUtil.generateRandomString(24); final long now = System.currentTimeMillis(); @@ -133,25 +140,55 @@ public Map getTokenInfo(String state, long now) throws ExpiredTo return _tinfo; } - public Map getRequestArgs(String state, ABCMeta request, int now) throws ExpiredToken { + public Map getTokenInfo(String state) throws ExpiredToken { + return getTokenInfo(state, 0); + } + + public Map getResponseArgs(String state, ABCMeta request, int now) throws ExpiredToken { Map info = state.getState(state); - Map requestArgs = new HashMap<>(); + Map responseArgs = new HashMap<>(); for (String claim : request.c_param) { if (claim.equals("accessToken")) { Map tInfo = this.getTokenInfo(state, now); if (tInfo == null) { continue; } - requestArgs.put(claim, tInfo.get("accessToken")); + responseArgs.put(claim, tInfo.get("accessToken")); } else { - requestArgs.put(claim, info.get(claim)); + responseArgs.put(claim, info.get(claim)); } } - return requestArgs; + return responseArgs; + } + + public DefaultSynthStyle.StateInfo addResponse(AuthorizationResponse authorizationResponse, String state) throws UnknownState { + if(!StringUtil.isNotNullAndNotEmpty(state)) { + state = authorizationResponse.getState(); + } + + DefaultSynthStyle.StateInfo stateInfo = this.getState(state); + if(stateInfo == null) { + throw new UnknownState(state); + } + + stateInfo.setCode(authorizationResponse.getCode()); + this.updateTokenInfo(stateInfo, authorizationResponse); + + for(String claim : Arrays.asList("idToken", "refreshToken")) { + stateInfo.setClaim(authorizationResponse.getClaim()); + } + + this.setState(stateInfo); + + return stateInfo; } public String getIdToken(String state) { return this.get(state).get("idToken"); } + + public void setClientId(String clientId) { + this.clientId = clientId; + } } diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java index 326fd5f..de8df65 100644 --- a/lib/src/main/java/oiccli/Util.java +++ b/lib/src/main/java/oiccli/Util.java @@ -20,12 +20,16 @@ public class Util { private static final String URL_ENCODED = "application/x-www-form-urlencoded"; private static final String JSON_ENCODED = "application/json"; + private static final String JRD_JSON = "application/jrd+json"; private static final String JWT_ENCODED = "application/jwt"; + private static final String PLAIN_TEXT = "text/plain"; + private static final String HTML_TEXT = "text/html"; private static final String JWT = "jwt"; private static final String JSON = "json"; private static final String URLENCODED = "urlencoded"; + private static final String TEXT = "txt"; private static final String DEFAULT_POST_CONTENT_TYPE = URL_ENCODED; - Map pairs = new HashMap() {{ + private static final Map pairs = new HashMap() {{ put("port", "portSpecified"); put("domain", "domainSpecified"); put("path", "pathSpecified"); @@ -59,22 +63,22 @@ public class Util { }}; public static Map getOrPost(String uri, String method, Message cis, Map args) throws UnsupportedEncodingException, UnsupportedType { - return getOrPost(uri, method, cis, "application/x-www-form-urlencoded", null, args); + return getOrPost(uri, method, cis, DEFAULT_POST_CONTENT_TYPE, null, args); } public static Map getOrPost(String uri, String method, Message request, String contentType, String accept, Map args) throws UnsupportedEncodingException, UnsupportedType { Map response = new HashMap<>(); String urlEncoded; if (method.equals("GET") || method.equals("DELETE")) { - urlEncoded = request.toUrlEncoded(request.toString()); + /*urlEncoded = request.toUrlEncoded(request.toString()); if (urlEncoded.contains("?")) { response.put("uri", uri + '&' + urlEncoded); } else { response.put("uri", uri + '?' + urlEncoded); - } + }*/ } else if (method.equals("POST") || method.equals("PUT")) { response.put("uri", uri); - if (contentType.equals("application/x-www-form-urlencoded")) { + if (contentType.equals(URL_ENCODED)) { response.put("body", request.toUrlEncoded(request.toString())); } else if (contentType.equals(JSON_ENCODED)) { response.put("body", request.toJSON(request.toHashMap())); @@ -94,6 +98,7 @@ public static Map getOrPost(String uri, String method, Message r } else { args.put("headers", headers); } + response.put("args", args); } else { throw new UnsupportedType("Unsupported HTTP method " + method); } @@ -179,13 +184,13 @@ public static boolean matchTo(String value, String valueExpected) { return valueExpected.startsWith(value); } - public String verifyHeader(FakeResponse response, String bodyType) throws WrongContentType, ValueError { + public static String verifyHeader(FakeResponse response, String bodyType) throws WrongContentType, ValueError { logger.debug("Response headers: " + response.getHeaders().toString()); logger.debug("Response txt: " + response.getText().toString()); String contentType = response.getHeaders().getContentType(); if (!StringUtil.isNotNullAndNotEmpty(contentType)) { - if (!StringUtil.isNotNullAndNotEmpty(bodyType)) { + if (StringUtil.isNotNullAndNotEmpty(bodyType)) { return bodyType; } else { return "txt"; @@ -195,19 +200,17 @@ public String verifyHeader(FakeResponse response, String bodyType) throws WrongC logger.debug("Expected body type: " + bodyType); if (bodyType.equals("")) { - if (matchTo(JSON_ENCODED, contentType)) { + if (matchTo(JSON_ENCODED, contentType) || matchTo(JRD_JSON, contentType)) { bodyType = JSON; } else if (matchTo(JWT_ENCODED, contentType)) { bodyType = JWT; } else if (matchTo(URL_ENCODED, contentType)) { bodyType = URLENCODED; } else { - bodyType = "txt"; + bodyType = TEXT; } } else if (bodyType.equals(JSON)) { - if (matchTo(JSON_ENCODED, contentType)) { - bodyType = JSON; - } else if (matchTo(JWT_ENCODED, contentType)) { + if (matchTo(JWT_ENCODED, contentType)) { bodyType = JWT; } else { throw new WrongContentType(contentType); @@ -218,9 +221,13 @@ public String verifyHeader(FakeResponse response, String bodyType) throws WrongC } } else if (bodyType.equals(URLENCODED)) { if (!matchTo(DEFAULT_POST_CONTENT_TYPE, contentType) && - !matchTo("text/plain", contentType)) { + !matchTo(PLAIN_TEXT, contentType)) { throw new WrongContentType(contentType); } + } else if(bodyType.equals(TEXT)) { + if(!matchTo(PLAIN_TEXT, contentType) && !matchTo(HTML_TEXT, contentType)) { + throw new WrongContentType("Content type: " + contentType); + } } else { throw new ValueError("Unknown return format: " + bodyType); } diff --git a/lib/src/main/java/oiccli/client_auth/BearerBody.java b/lib/src/main/java/oiccli/client_auth/BearerBody.java index aac5b72..ae778e0 100644 --- a/lib/src/main/java/oiccli/client_auth/BearerBody.java +++ b/lib/src/main/java/oiccli/client_auth/BearerBody.java @@ -1,14 +1,20 @@ package oiccli.client_auth; +import com.auth0.jwt.jwts.JWT; +import oiccli.State; +import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; +import java.security.Key; import java.util.HashMap; +import java.util.List; import java.util.Map; public class BearerBody { - public Map> construct(Map cis, CliInfo cliInfo, Map requestArgs, Map> httpArgs, - Map args) throws AuthenticationFailure { + public Map> construct(Map cis, ClientInfo clientInfo, Map requestArgs, Map> httpArgs, + Map args) throws AuthenticationFailure { if (requestArgs == null) { requestArgs = new HashMap<>(); } @@ -19,7 +25,7 @@ public Map> construct(Map cis, CliIn cis.put("accessToken", accessToken); } else { if (args.get("state") == null) { - String state = cliInfo.getState(); + State state = clientInfo.getState(); if (state == null) { throw new AuthenticationFailure("Missing state specification"); } @@ -27,10 +33,19 @@ public Map> construct(Map cis, CliIn args.put("state", state); } - cis.put("accessToken", cliInfo.getStateDb().getTokenInfo(args).get("accessToken")); + cis.put("accessToken", clientInfo.getStateDb().getTokenInfo(args).get("accessToken")); } } return httpArgs; } + + public static JWT assertionJWT(String clientId, List keys, List audience, + String algorithm, int lifeTime) { + long now = System.currentTimeMillis(); + + AuthenticationToken at = new AuthenticationToken(clientId, clientId, audience, StringUtil.generateRandomString(32), + now + lifeTime, now); + return at.toJwt(keys, algorithm); + } } diff --git a/lib/src/main/java/oiccli/client_auth/BearerHeader.java b/lib/src/main/java/oiccli/client_auth/BearerHeader.java index dfa47e8..67dd981 100644 --- a/lib/src/main/java/oiccli/client_auth/BearerHeader.java +++ b/lib/src/main/java/oiccli/client_auth/BearerHeader.java @@ -1,11 +1,13 @@ package oiccli.client_auth; +import oiccli.client_info.ClientInfo; + import java.util.HashMap; import java.util.Map; public class BearerHeader { - public Map> construct(Map cis, CliInfo cliInfo, Map requestArgs, Map> httpArgs, + public Map> construct(Map cis, ClientInfo clientInfo, Map requestArgs, Map> httpArgs, Map args) { String accessToken; if (cis != null) { @@ -20,8 +22,7 @@ public Map> construct(Map cis, CliIn if (accessToken != null) { accessToken = args.get("accessToken"); if (accessToken == null) { - //_acc_token = cli_info.state_db.get_token_info( - // **kwargs)['access_token'] + accessToken = clientInfo.getStateDb().getTokenInfo(args).get("accessToken"); } } } @@ -48,16 +49,4 @@ public Map> construct(Map cis, CliIn return httpArgs; } - - public static String bearerAuth(Map req, String authentication) { - if (req.containsKey("accessToken")) { - return req.get("accessToken"); - } else { - if (authentication.startsWith("Bearer ")) { - return authentication.substring(7); - } else { - throw new IllegalArgumentException("Authentication " + authentication + " is invalid"); - } - } - } } diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java index 6471fde..38ae30a 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java @@ -3,6 +3,7 @@ import com.auth0.jwt.jwts.JWT; import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; import org.apache.commons.codec.binary.Base64; import org.apache.commons.text.CharacterPredicates; import org.apache.commons.text.RandomStringGenerator; @@ -15,23 +16,27 @@ public class ClientSecretBasic extends ClientAuthenticationMethod { - private final static Logger logger = LoggerFactory.getLogger(ClientAuth.class); + private final static Logger logger = LoggerFactory.getLogger(ClientSecretBasic.class); public static JWT assertionJwt(String clientId, List keys, List audience, String algorithm, int lifetime) { long now = System.currentTimeMillis(); String jti = StringUtil.generateRandomString(32); - AuthToken token = new AuthToken(clientId, clientId, audience, jti, now + lifetime, now); + AuthenticationToken token = new AuthenticationToken(clientId, clientId, audience, jti, now + lifetime, now); logger.debug("AuthnToken " + token.toString()); return token.toJWT(keys, algorithm); } - public Map> construct(Map cis, CliInfo cliInfo, Map> httpArgs, + public Map> construct(Map cis, ClientInfo cliInfo, Map> httpArgs, Map args) { if (httpArgs == null) { httpArgs = new HashMap<>(); } + if(!httpArgs.containsKey("headers")) { + httpArgs.put("headers", new HashMap()); + } + String password = args.get("password"); if (password == null) { password = httpArgs.get("password").get("password"); @@ -48,15 +53,11 @@ public Map> construct(Map cis, CliIn user = cliInfo.getClientId(); } - if (!httpArgs.keySet().contains("headers")) { - httpArgs.put("headers", null); - } - String credentials = user + ":" + password; - String authz = Base64.encodeBase64(credentials.getBytes()); + String authz = new String(Base64.encodeBase64(credentials.getBytes())); Map hMap = httpArgs.get("headers"); hMap.put("Authorization", "Basic " + authz); - + httpArgs.put("headers", hMap); cis.remove("clientSecret"); diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java index daeab2d..04c07c7 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java @@ -1,16 +1,19 @@ package oiccli.client_auth; import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.AuthenticationFailure; +import java.security.Key; import java.util.Map; public class ClientSecretJwt extends JWSAuthenticationMethod { - public String chooseAlgorithm(String entity, Map args) { + public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { return JWSAuthenticationMethod.chooseAlgorithm(entity, args); } - public Key getSigningKey(String algorithm, CliInfo cliInfo) { - return cliInfo.keyjar.getSigningKey(StringUtil.alg2keytype(algorithm), algorithm); + public Key getSigningKey(String algorithm, ClientInfo clientInfo) { + return clientInfo.getKeyJar().getSigningKey(StringUtil.alg2keytype(algorithm), algorithm); } } diff --git a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java index cfd7196..9e71d4a 100644 --- a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java +++ b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java @@ -1,6 +1,7 @@ package oiccli.client_auth; import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; import java.util.Arrays; @@ -10,11 +11,12 @@ import org.junit.Assert; import static org.junit.Assert.assertTrue; +import java.util.List; import java.util.Map; public class JWSAuthenticationMethod extends ClientAuthenticationMethod { - private static final Map DEF_SIGN_ALG = new HashMap<>() {{ + private static final Map DEF_SIGN_ALG = new HashMap() {{ put("id_token", "RS256"); put("userinfo", "RS256"); put("request_object", "RS256"); @@ -27,9 +29,9 @@ public static String chooseAlgorithm(String entity, Map args) th String algorithm = args.get("algorithm"); if (algorithm == null) { algorithm = DEF_SIGN_ALG.get(entity); - } - if (algorithm != null) { - throw new AuthenticationFailure("Missing algorithm specification"); + if (algorithm == null) { + throw new AuthenticationFailure("Missing algorithm specification"); + } } return algorithm; @@ -39,13 +41,13 @@ public String chooseAlgorithm(Map args) throws AuthenticationFai return chooseAlgorithm(null, args); } - public Key getSigningKey(String algorithm, CliInfo cliInfo) { - return cli_info.keyjar.get_signing_key( - StringUtil.alg2keytype(algorithm), alg = algorithm); + public Key getSigningKey(String algorithm, ClientInfo clientInfo) { + return clientInfo.getKeyJar().getSigningKey( + StringUtil.alg2keytype(algorithm), algorithm); } - public Key getKeyByKid(String kid, String algorithm, CliInfo cliInfo) throws NoMatchingKey { - Key key = cli_info.keyjar.get_key_by_kid(kid); + public Key getKeyByKid(String kid, String algorithm, ClientInfo clientInfo) throws NoMatchingKey { + Key key = clientInfo.getKeyJar().getKeyByKid(kid); String ktype; if (key != null) { ktype = StringUtil.alg2keytype(algorithm); @@ -60,10 +62,10 @@ public Key getKeyByKid(String kid, String algorithm, CliInfo cliInfo) throws NoM } } - public Map construct(Map cis, CliInfo cliInfo, Map requestArgs, + public Map construct(Map cis, ClientInfo clientInfo, Map requestArgs, Map httpArgs, Map args) throws AuthenticationFailure, NoMatchingKey { String algorithm = null; - String audience = null; + List audience = null; if (args.containsKey("clientAssertion")) { cis.put("clientAssertion", args.get("clientAssertion")); if (args.containsKey("clientAssertionType")) { @@ -77,10 +79,10 @@ public Map construct(Map cis, CliInfo cliInfo, M } } else { if (args.get("authenticationEndpoint").equals("token") || args.get("authenticationEndpoint").equals("refresh")) { - algorithm = cliInfo.registrationInfo("tokenEndpointAuthSigningAlg"); - audience = cliInfo.providerInfo("tokenEndpoint"); + algorithm = clientInfo.registrationInfo("tokenEndpointAuthSigningAlg"); + audience = clientInfo.getProviderInfo().get("tokenEndpoint"); } else { - audience = cliInfo.providerInfo("issuer"); + audience = clientInfo.getProviderInfo().get("issuer"); } } @@ -91,24 +93,24 @@ public Map construct(Map cis, CliInfo cliInfo, M String ktype = StringUtil.alg2keytype(algorithm); List signingKey = null; if (args.containsKey("kid")) { - signingKey = (List) Arrays.asList(this.getKeyByKid(args.get("kid"), algorithm, cliInfo)); - } else if (cliInfo.kid("sig").contains(ktype)) { - Key key = this.getKeyByKid(args.get("sig")["ktype"], algorithm, cliInfo); + signingKey = Arrays.asList(this.getKeyByKid(args.get("kid"), algorithm, clientInfo)); + } else if (clientInfo.getKid().get("sig").containsKey(ktype)) { + Key key = this.getKeyByKid(clientInfo.getKid().get("sig").get("ktype"), algorithm, clientInfo); if (key != null) { - signingKey = (List) Arrays.asList(key); + signingKey = Arrays.asList(key); } else { - signingKey = this.getSigningKey(algorithm, cliInfo); + signingKey = Arrays.asList(this.getSigningKey(algorithm, clientInfo)); } } Map hMap = new HashMap<>(); hMap.put("lifetime", args.get("lifetime")); - cis.put("clientAssertion", assertionJWT(cliInfo.getClientId(), signingKey, audience, algorithm, args)); + cis.put("clientAssertion", BearerBody.assertionJWT(clientInfo.getClientId(), signingKey, audience, algorithm, 600)); cis.put("clientAssertionType", JWT_BEARER); cis.remove("clientSecret"); - if (cis.cParam["clientId"][VREQUIRED]) { + if (cis.get("clientId").get(1)) { cis.remove("clientId"); } diff --git a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java index 9fd23d1..7aeb364 100644 --- a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java +++ b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java @@ -1,8 +1,10 @@ package oiccli.client_auth; import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; +import java.security.Key; import java.util.Map; public class PrivateKeyJwt extends JWSAuthenticationMethod { @@ -15,7 +17,7 @@ public String chooseAlgorithm(Map args) throws AuthenticationFai return chooseAlgorithm("private_key_jwt", args); } - public Key getSigningKey(String algorithm, CliInfo cliInfo) { - return cliInfo.keyjar.getSigningKey(StringUtil.alg2keytype(algorithm), "", algorithm); + public Key getSigningKey(String algorithm, ClientInfo clientInfo) { + return clientInfo.getKeyJar().getSigningKey(StringUtil.alg2keytype(algorithm), "", algorithm); } } diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java index 03a06df..2bb590e 100644 --- a/lib/src/main/java/oiccli/client_info/ClientInfo.java +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -2,7 +2,9 @@ import com.google.common.collect.ImmutableMap; import com.sun.org.apache.xml.internal.security.utils.Base64; +import oiccli.State; import oiccli.StringUtil; +import oiccli.exceptions.ExpiredToken; import org.junit.Assert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,7 +27,7 @@ public class ClientInfo { "alg", "requestObjectEncryptionAlg", "enc", "requestObjectEncryptionEnc"); private static final Map> attributeMap = - ImmutableMap.of("userinfo", userInfoMap, "id_token", idTokenMap, "request", requestMap); + ImmutableMap.of("userinfo", userInfoMap, "idToken", idTokenMap, "request", requestMap); private static final Map defSignAlg = ImmutableMap.of("idToken", "RS256", "userInfo", "RS256", @@ -33,9 +35,8 @@ public class ClientInfo { "clientSecretJwt", "HS256", "privateKeyJwt", "RS256"); - private KeyJar keyJar; - private Database stateDb; + private State stateDb; private List events; private boolean shouldBeStrictOnPreferences; private Map> providerInfo; @@ -43,7 +44,7 @@ public class ClientInfo { private String registrationExpires; private String registrationAccessToken; private Map> kid; - private Map config; + private Map> config; private Map allow; private Map> behavior; private Map> clientPrefs; @@ -92,9 +93,9 @@ public ClientInfo(KeyJar keyjar, Map config, List events this.getClass().getField(attribute).set(attribute, ""); } - if (attribute.equals("clientId")) { + /*if (attribute.equals("clientId")) { this.stateDb.setClientId(config.get(attribute)); - } + }*/ } attributes = new ArrayList<>(Arrays.asList("allow", "clientPrefs", "behavior", "providerInfo")); @@ -124,6 +125,38 @@ public ClientInfo(KeyJar keyjar, Map config, List events } else { this.redirectUris = null; } + + this.importKeys(config.get("keys")); + + if(config.containsKey("keydefs")) { + this.keyJar = buildKeyJar(config.get("keydefs"), this.keyJar)[1]; + } + } + + public void importKeys(Map>> keySpec) { + for(String key : keySpec.keySet()) { + if(key.equals("file")) { + Map> hMap = keySpec.get(key); + for(String hMapKey : hMap.keySet()) { + if(hMapKey.equals("rsa")) { + Key key; + KeyBundle keyBundle; + for(String file : hMap.get(hMapKey)) { + key = new RSAKey(importPrivateRsaKeyFromFile(file), "sig"); + keyBundle = new KeyBundle(); + keyBundle.append(key); + this.keyJar.addKb("", keyBundle); + } + } + } + } else if(key.equals("url")) { + KeyBundle keyBundle; + for(String issuer : keySpec.keySet()) { + keyBundle = new KeyBundle(keySpec.get(issuer)); + this.keyJar.addKb(keyBundle); + } + } + } } public String getCSecret() { @@ -162,10 +195,14 @@ public String getClientSecret() { return cSecret; } + public Map> getKid() { return kid; } + public void setClientSecret(String cSecret) { this.cSecret = cSecret; } + public State getState() { return stateDb; } + public void setCSecret(String secret) { if (secret == null) { this.cSecret = ""; @@ -187,6 +224,7 @@ public String getClientId() { public void setClientId(String clientId) { this.cId = clientId; + this.stateDb.setClientId(clientId); } public void setRegistrationResponse(Map registrationResponse) { @@ -213,11 +251,11 @@ public KeyJar getKeyJar() { return keyJar; } - public Database getStateDb() { + public State getStateDb() { return stateDb; } - public void setStateDb(Database stateDb) { + public void setStateDb(State stateDb) { this.stateDb = stateDb; } @@ -239,9 +277,11 @@ public String filenameFromWebname(String webName) { public Map signEncAlgs(SignEncAlgs type) { Map response = new HashMap<>(); + String value; for (String key : attributeMap.get(type).keySet()) { - if (attributeMap.get(key) != null && this.registrationResponse.get(attributeMap.get(key)) != null) { - response.put(key, this.registrationResponse.get(attributeMap.get(key))); + value = this.registrationResponse.get(attributeMap.get(key)); + if (attributeMap.get(key) != null && value != null) { + response.put(key, value); } else { if (key.equals("sign")) { response.put(key, defSignAlg.get(type)); @@ -253,10 +293,7 @@ public Map signEncAlgs(SignEncAlgs type) { } public boolean verifyAlgSupport(String algorithm, VerifyAlgSupportUsage usage, VerifyAlgSupportType type) { - // THIS RELATES TO CLIINFO - ask Roland how to implement it - // supported = self.provider_info[ - //"{}_{}_values_supported".format(usage, typ)] - + List supported = this.providerInfo.get(usage + "" + type + "valuesSupported"); return supported.contains(algorithm); } @@ -273,19 +310,16 @@ public List generateRequestUris(String requestsDir) { return this.baseUrl + requestsDir + "/" + m.hexDigest(); } - public static List addCodeChallenge(ClientInfo clientInfo) { - String codeChallengeFromMap = clientInfo.config.get("codeChallenge"); - int cvLength; - if (codeChallengeFromMap != null) { - cvLength = codeChallengeFromMap.length(); - } else { + public static List addCodeChallenge(ClientInfo clientInfo, String state) { + Integer cvLength = (Integer) clientInfo.config.get("codeChallenge").get("length"); + if(cvLength == null) { cvLength = 64; } String codeVerifier = StringUtil.generateRandomString(cvLength); codeVerifier = Base64.encode(codeVerifier.getBytes()); - String method = clientInfo.config['code_challenge']['method']; + String method = (String) clientInfo.config.get("codeChallenge").get("method"); if (method == null) { method = "S256"; } @@ -299,6 +333,8 @@ raise Unsupported( 'PKCE Transformation method:{}'.format(_method)) */ + clientInfo.getStateDb().addInfo(state, null); + Map hMap = new HashMap<>(); hMap.put("codeChallenge", codeChallenge); hMap.put("codeChallengeMethod", method); @@ -309,4 +345,8 @@ raise Unsupported( public void setRegistrationExpires(String registrationExpires) { this.registrationExpires = registrationExpires; } + + public static Object getCodeVerifier(ClientInfo clientInfo, String state) throws ExpiredToken { + return clientInfo.getStateDb().getTokenInfo("state"+state).get("codeVerifier"); + } } diff --git a/lib/src/main/java/oiccli/exceptions/AtHashError.java b/lib/src/main/java/oiccli/exceptions/AtHashError.java new file mode 100644 index 0000000..09050e4 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/AtHashError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class AtHashError extends Exception{ + public AtHashError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/CHashError.java b/lib/src/main/java/oiccli/exceptions/CHashError.java new file mode 100644 index 0000000..af5ce6d --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/CHashError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class CHashError extends Exception{ + public CHashError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/MessageException.java b/lib/src/main/java/oiccli/exceptions/MessageException.java new file mode 100644 index 0000000..c7bf36a --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/MessageException.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class MessageException extends Exception{ + public MessageException(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java b/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java new file mode 100644 index 0000000..d6e1b82 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class MissingRequiredAttribute extends Exception{ + public MissingRequiredAttribute(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/OicMsgError.java b/lib/src/main/java/oiccli/exceptions/OicMsgError.java new file mode 100644 index 0000000..4c507c0 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/OicMsgError.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class OicMsgError extends Exception{ + public OicMsgError(String message) { + super(message); + } +} diff --git a/lib/src/main/java/oiccli/exceptions/UnknownState.java b/lib/src/main/java/oiccli/exceptions/UnknownState.java new file mode 100644 index 0000000..5d68355 --- /dev/null +++ b/lib/src/main/java/oiccli/exceptions/UnknownState.java @@ -0,0 +1,7 @@ +package oiccli.exceptions; + +public class UnknownState extends Throwable { + public UnknownState(String state) { + super(state); + } +} diff --git a/lib/src/main/java/oiccli/service/AccessToken.java b/lib/src/main/java/oiccli/service/AccessToken.java index 740f0cd..70f411c 100644 --- a/lib/src/main/java/oiccli/service/AccessToken.java +++ b/lib/src/main/java/oiccli/service/AccessToken.java @@ -1,6 +1,9 @@ package oiccli.service; +import oiccli.AuthorizationResponse; +import oiccli.client_info.ClientInfo; import oiccli.exceptions.ParameterError; +import oiccli.exceptions.UnknownState; import java.util.Arrays; import java.util.Map; @@ -16,7 +19,8 @@ public AccessToken(String httpLib, KeyJar keyJar, String clientAuthenticationMet this.postParseResponse = Arrays.asList(this.oicPostParseResponse); } - public void oicPostParseResponse(Map> response, CliInfo cliInfo, String state) throws ParameterError { + public void oicPostParseResponse(AuthorizationResponse response, ClientInfo cliInfo, String state) throws ParameterError, UnknownState { + cliInfo.getStateDb().addResponse(response, state); Map idt = response.get("verifiedIdToken"); if (!cliInfo.getStateDb().nonceToState(idt.get("nonce")).equals(state)) { diff --git a/lib/src/main/java/oiccli/service/Authorization.java b/lib/src/main/java/oiccli/service/Authorization.java index 0a5e362..d50f37e 100644 --- a/lib/src/main/java/oiccli/service/Authorization.java +++ b/lib/src/main/java/oiccli/service/Authorization.java @@ -1,6 +1,8 @@ package oiccli.service; +import oiccli.AuthorizationResponse; import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; import java.io.BufferedWriter; import java.io.FileWriter; @@ -27,10 +29,15 @@ public Authorization(Object httpLib, Object keyJar, Map clientAut self.post_construct = [self.oic_post_construct]*/ } - public List> oicPreConstruct(CliInfo cliInfo, Map requestArgs, Map args) { + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { if (requestArgs != null) { - String responseType = requestArgs.get("responseType"); - if (responseType.contains("token") || responseType.contains("id_token")) { + String responseType = (String) requestArgs.get("responseType"); + if(responseType == null) { + requestArgs.put("responseType", clientInfo.getBehavior().get("responseTypes").get(0)); + + } + + if (responseType.contains("token") || responseType.contains("idToken")) { if (!requestArgs.containsKey("nonce")) { requestArgs.put("nonce", StringUtil.generateRandomString(32)); } @@ -56,15 +63,19 @@ public List> oicPreConstruct(CliInfo cliInfo, Map responseMode = clientInfo.getBehavior().get("responseMode"); + if (responseMode.contains("formPost")) { requestArgs.put("responseMode", responseMode); } + if(!requestArgs.containsKey("state")) { + requestArgs.put("state", clientInfo.getStateDb().createState(clientInfo.getIssuer(), requestArgs)); + } + return Arrays.asList(requestArgs, postArgs); } - public Map oicPostConstruct(CliInfo cliInfo, Map req, Map args) { + public Map oicPostConstruct(ClientInfo clientInfo, Map req, Map args) { String requestParam = args.get("requestParam"); args.remove("requestParam"); @@ -74,7 +85,7 @@ public Map oicPostConstruct(CliInfo cliInfo, Map } if (algorithm == null) { - algorithm = cliInfo.getBehavior("requestObjectSigningAlg"); + algorithm = clientInfo.getBehavior().get("requestObjectSigningAlg"); if (algorithm == null) { algorithm = "RS256"; } @@ -86,9 +97,9 @@ public Map oicPostConstruct(CliInfo cliInfo, Map String kty = StringUtil.alg2keytype(algorithm); String kid = args.get("sigKid"); if (kid == null) { - kid = cliInfo.getKid("sig").get(kty, null); + kid = clientInfo.getKid().get("sig").get(kty); } - args.put("keys", cliInfo.getKeyJar().getSigningKey(kty, kid)); + args.put("keys", clientInfo.getKeyJar().getSigningKey(kty, kid)); } /* @@ -102,7 +113,7 @@ public Map oicPostConstruct(CliInfo cliInfo, Map req.put("request", _req); } else { //_webname = cli_info.registration_response['request_uris'][0] - String fileName = cliInfo.fileNameFromWebName(webname); + String fileName = clientInfo.filenameFromWebname(webName); //except KeyError: //filename, _webname = construct_request_uri(**kwargs) BufferedWriter writer = null; diff --git a/lib/src/main/java/oiccli/service/CheckID.java b/lib/src/main/java/oiccli/service/CheckID.java index 3123674..778cd78 100644 --- a/lib/src/main/java/oiccli/service/CheckID.java +++ b/lib/src/main/java/oiccli/service/CheckID.java @@ -2,6 +2,7 @@ import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; import oiccli.service.Service; import oiccli.service.UserInfo; @@ -23,7 +24,7 @@ public CheckID(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) //self.pre_construct = [self.oic_pre_construct] } - public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) throws MissingParameter { requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); return Arrays.asList(requestArgs, new HashMap()); } diff --git a/lib/src/main/java/oiccli/service/CheckSession.java b/lib/src/main/java/oiccli/service/CheckSession.java index 74b6bf8..06d7617 100644 --- a/lib/src/main/java/oiccli/service/CheckSession.java +++ b/lib/src/main/java/oiccli/service/CheckSession.java @@ -2,6 +2,7 @@ import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; import java.util.Arrays; import java.util.HashMap; @@ -21,7 +22,7 @@ public CheckSession(String httpLib, KeyJar keyJar, String clientAuthenticationMe //self.pre_construct = [self.oic_pre_construct] } - public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) throws MissingParameter { requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); return Arrays.asList(requestArgs, new HashMap()); } diff --git a/lib/src/main/java/oiccli/service/EndSession.java b/lib/src/main/java/oiccli/service/EndSession.java index 8d92250..4e148ea 100644 --- a/lib/src/main/java/oiccli/service/EndSession.java +++ b/lib/src/main/java/oiccli/service/EndSession.java @@ -2,6 +2,7 @@ import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; import java.util.Arrays; import java.util.HashMap; @@ -21,7 +22,7 @@ public EndSession(String httpLib, KeyJar keyJar, String clientAuthenticationMeth //self.pre_construct = [self.oic_pre_construct] } - public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) throws MissingParameter { requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); return Arrays.asList(requestArgs, new HashMap()); } diff --git a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java index ed06384..f07e743 100644 --- a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java +++ b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java @@ -1,5 +1,6 @@ package oiccli.service; +import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; import oiccli.exceptions.ConfigurationError; import org.slf4j.Logger; @@ -54,12 +55,21 @@ public static void matchPreferences(ClientInfo clientInfo, Map> behavior = clientInfo.getBehavior(); - behavior.put(key, Arrays.asList(value)); + behavior.put(key, Arrays.asList(valueIndex)); clientInfo.setBehavior(behavior); + break; } } } @@ -69,43 +79,26 @@ public static void matchPreferences(ClientInfo clientInfo, Map behavior = clientInfo.getBehavior().get(keyIndex); + if (behavior == null) { + behavior = new ArrayList<>(); + } + behavior.addAll(clientInfo.getClientPrefs().get(keyIndex)); + } + } + } logger.debug("cliInfo behavior " + clientInfo.getBehavior().toString()); diff --git a/lib/src/main/java/oiccli/service/UserInfo.java b/lib/src/main/java/oiccli/service/UserInfo.java index a7d8c27..9d04e2c 100644 --- a/lib/src/main/java/oiccli/service/UserInfo.java +++ b/lib/src/main/java/oiccli/service/UserInfo.java @@ -3,6 +3,8 @@ import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; import oiccli.exceptions.MissingParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; @@ -12,9 +14,10 @@ public class UserInfo extends Service { private UserInfoErrorResponse userInfoErrorResponse; private static String endpointName = "userInfoEndpoint"; private static boolean isSynchronous = true; - private String request = "userInfo"; - private String defaultAuthenticationMethod = "bearerHeader"; - private String httpMethod = "POST"; + private static String request = "userInfo"; + private static String defaultAuthenticationMethod = "bearerHeader"; + private static String httpMethod = "GET"; + private final static Logger logger = LoggerFactory.getLogger(UserInfo.class); public UserInfo(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { super(httpLib, keyJar, clientAuthenticationMethod); @@ -37,11 +40,10 @@ public List> oicPreConstruct(ClientInfo clientInfo, Map()); } - /* - def oic_post_parse_response(self, resp, client_info, **kwargs): - resp = self.unpack_aggregated_claims(resp, client_info) - return self.fetch_distributed_claims(resp, client_info) - */ + public Map> oicPostParseResponse(Map> userInfo, ClientInfo clientInfo) { + Map> unpacked = this.unpackAggregatedClaims(userInfo, clientInfo); + return this.fetchDistributedClaims(unpacked, clientInfo, null); + } public Map> unpackAggregatedClaims(Map> userInfo, ClientInfo clientInfo) { Map csrc = userInfo.get("claimSources"); @@ -55,7 +57,7 @@ public Map> unpackAggregatedClaims(Map) mapEntry.getValue(); if (value.containsKey("JWT")) { - Map aggregatedClaims = new Message().fromJWT(value.get("JWT"), clientInfo.getKeyJar()); + Map> aggregatedClaims = new Message().fromJWT(value.get("JWT"), clientInfo.getKeyJar()); Map cName = userInfo.get("claimNames"); set = cName.entrySet(); iterator = set.iterator(); @@ -64,10 +66,13 @@ public Map> unpackAggregatedClaims(Map) mapEntryInner.getValue(); - /*if(valueInner) - + if (valueInner.equals(value)) { + claims.add(keyInner); + } + } - */ + for (String claim : claims) { + userInfo.put(claim, aggregatedClaims.get(claim)); } } } @@ -75,7 +80,7 @@ public Map> unpackAggregatedClaims(Map> fetchDistributedClaims(Map> userInfo, ClientInfo clientInfo, Object callBack) { + public Map> fetchDistributedClaims(Map> userInfo, ClientInfo clientInfo, Method callBack) { Map csrc = userInfo.get("claimSources"); Set set = csrc.entrySet(); Iterator iterator = set.iterator(); @@ -86,41 +91,42 @@ public Map> fetchDistributedClaims(Map) mapEntry.getValue(); + ErrorResponse errorResponse; if (value.containsKey("endpoint")) { if (value.containsKey("accessToken")) { - /* - _uinfo = self.service_request( - spec["endpoint"], method='GET', - token=spec["access_token"], client_info=cli_info) - */ + //TODO:callback is a method; figure out how to pass a method as a param to a function + errorResponse = oiccli.Service.serviceRequest(value.get("endpoint"), "GET", value.get("accessToken"), clientInfo); } else { if (callBack != null) { - /*_uinfo = self.service_request( - spec["endpoint"], - method='GET', - token=callback(spec['endpoint']), - client_info=cli_info)*/ + errorResponse = oiccli.Service.serviceRequest(value.get("endpoint"), "GET", callBack(value.get("endpoint")), clientInfo); } else { - /* - _uinfo = self.service_request( - spec["endpoint"], - method='GET', - client_info=cli_info) - */ + errorResponse = oiccli.Service.serviceRequest(value.get("endpoint"), "GET", clientInfo); } } - /* - claims = [value for value, src in - userinfo["_claim_names"].items() if src == csrc] - */ + List claims = new ArrayList<>(); + Set keys = userInfo.get("claimNames").keySet(); + String valueIndex; + for (String keyIndex : keys) { + valueIndex = userInfo.get("claimNames").get(keyIndex); + if (valueIndex.equals(key)) { + claims.add(valueIndex); + } + } + if (new HashSet<>(claims).equals(new HashSet<>(errorResponse.getKeys()))) { + logger.warn("Claims from claim source doesn't match what's in the userinfo"); + } + for (String errorResponseKey : errorResponse.keySet()) { + userInfo.put(errorResponseKey, errorResponse.get(errorResponseKey)); + } } } + return userInfo; } - public static Map setIdToken(ClientInfo cliInfo, Map requestArgs, Map args) { + public static Map setIdToken(ClientInfo cliInfo, Map requestArgs, Map args) throws MissingParameter { if (requestArgs == null) { requestArgs = new HashMap<>(); } @@ -132,16 +138,12 @@ public static Map setIdToken(ClientInfo cliInfo, Map rel) throws URISyntaxException, WebFingerError { resource = new URINormalizer().normalize(resource); - List queryParamsTuple = new ArrayList<>(); - queryParamsTuple.add(new Tuple("resource", resource)); + List queryParamsTuple = new ArrayList<>(Arrays.asList(new Tuple("resource", resource))); if(rel == null) { - if(this.defaultRelt != null) { + if(StringUtil.isNotNullAndNotEmpty(this.defaultRelt)) { queryParamsTuple.add(new Tuple("rel", this.defaultRelt)); } } else { @@ -102,6 +105,8 @@ public Map> httpArgs(JRD jrd) { return headersAndBody; } + /* + TODO: I don't see this in Roland's code anymore; might want to remove public String discoveryQuery(String resource) throws URISyntaxException, WebFingerError { logger.debug("Looking for OIDC OP for '" + resource + "'"); String url = this.query(resource, Arrays.asList(OIC_ISSUER)); @@ -134,9 +139,9 @@ public String discoveryQuery(String resource) throws URISyntaxException, WebFing } else { throw new WebFingerError("Status code is: " + statusCode); } - } + }*/ - public String response(String subject, String base, Map args) throws NoSuchFieldException, IllegalAccessException { + /*public String response(String subject, String base, Map args) throws NoSuchFieldException, IllegalAccessException { this.jrd = new JRD(); this.jrd.setSubject(subject); Base.link.put("rel", OIC_ISSUER); @@ -146,5 +151,49 @@ public String response(String subject, String base, Map args) thr this.jrd.getClass().getField(key).set(key, args.get(key)); } return json.dumps(this.jrd.export()); + }*/ + + + public static Object linkDeser(Object val, String sFormat) { + if(val instanceof Map) { + return val; + } else if(sFormat.equals("dict") || sFormat.equals("json")) { + if(!(val instanceof String)) { + val = json.dumps(val); + sFormat = "json"; + } + } + + return link().deserialize(val, sFormat); + } + + public static Object messageSer(Object inst, String sFormat, int lev) throws MessageException, OicMsgError { + Object res; + if(sFormat.equals("urlencoded") || sFormat.equals("json")) { + if(inst instanceof Map) { + if(sFormat.equals("json")) { + res = json.dumps(inst); + } else { + res = Base64.encodeBase64URLSafe() + } + } + //elif isinstance(inst, LINK): + //res = inst.serialize(sformat, lev) + else { + res = inst; + } + } else if(sFormat.equals("dict")) { + if(inst instanceof Map) { + res = inst.serialize(sFormat, lev); + } else if(inst instanceof String) { + res = inst; + } else { + throw new MessageException("Wrong type: " + inst.getClass()); + } + } else { + throw new OicMsgError("Unknown sFormat" + inst); + } + + return res; } } From 8f88eacd6d1e4875eddc3f5a62ffff8d785fb9ca Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Wed, 24 Jan 2018 11:51:39 -0800 Subject: [PATCH 05/10] Code style changes --- lib/build.gradle | 6 +- lib/src/main/java/oiccli/AES.java | 4 +- .../java/oiccli/AuthorizationResponse.java | 28 ++++---- lib/src/main/java/oiccli/ErrorMessage.java | 2 +- lib/src/main/java/oiccli/HTTP/Http.java | 2 + lib/src/main/java/oiccli/HTTP/Response.java | 7 +- lib/src/main/java/oiccli/Service.java | 14 +++- lib/src/main/java/oiccli/State.java | 6 +- lib/src/main/java/oiccli/Util.java | 4 +- .../oiccli/client_auth/ClientSecretBasic.java | 5 +- .../oiccli/client_auth/ClientSecretJwt.java | 1 + .../oiccli/client_auth/ClientSecretPost.java | 2 - .../client_auth/JWSAuthenticationMethod.java | 7 +- .../oiccli/client_auth/PrivateKeyJwt.java | 2 + .../java/oiccli/client_info/ClientInfo.java | 38 ++++++---- .../main/java/oiccli/exceptions/AESError.java | 2 +- .../java/oiccli/exceptions/AtHashError.java | 2 +- .../exceptions/AuthenticationFailure.java | 2 +- .../java/oiccli/exceptions/CHashError.java | 2 +- .../oiccli/exceptions/ConfigurationError.java | 2 +- .../java/oiccli/exceptions/ExpiredToken.java | 2 +- .../oiccli/exceptions/MessageException.java | 2 +- .../oiccli/exceptions/MissingEndpoint.java | 2 +- .../oiccli/exceptions/MissingParameter.java | 2 +- .../exceptions/MissingRequiredAttribute.java | 2 +- .../java/oiccli/exceptions/NoMatchingKey.java | 2 +- .../java/oiccli/exceptions/OicCliError.java | 2 +- .../java/oiccli/exceptions/OicMsgError.java | 2 +- .../oiccli/exceptions/UnsupportedType.java | 2 +- .../java/oiccli/exceptions/ValueError.java | 2 +- .../oiccli/exceptions/WebFingerError.java | 2 +- .../oiccli/exceptions/WrongContentType.java | 2 +- .../java/oiccli/service/Authorization.java | 4 +- lib/src/main/java/oiccli/service/CheckID.java | 2 - .../main/java/oiccli/service/EndSession.java | 4 +- .../oiccli/service/ProviderInfoDiscovery.java | 11 ++- lib/src/main/java/oiccli/service/Service.java | 1 - .../main/java/oiccli/service/UserInfo.java | 9 ++- lib/src/main/java/oiccli/webfinger/Base.java | 70 ++++++++++++------- lib/src/main/java/oiccli/webfinger/JRD.java | 33 ++++++--- .../java/oiccli/webfinger/URINormalizer.java | 18 +++-- .../main/java/oiccli/webfinger/WebFinger.java | 70 ++++++++++--------- 42 files changed, 221 insertions(+), 163 deletions(-) diff --git a/lib/build.gradle b/lib/build.gradle index 68c57fe..dc05b99 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -37,14 +37,12 @@ dependencies { compile 'com.fasterxml.jackson.core:jackson-databind:2.9.2' compile 'commons-codec:commons-codec:1.11' compile 'com.google.code.gson:gson:2.8.2' - compile group: 'org.apache.commons', name: 'commons-text', version: '1.1' - compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.6.1' - compile 'junit:junit:4.12' - compile "com.google.guava:guava:16+" + compile 'com.google.guava:guava:r05' testCompile 'org.bouncycastle:bcprov-jdk15on:1.58' testCompile 'net.jodah:concurrentunit:0.4.3' testCompile 'org.hamcrest:java-hamcrest:2.0.0.0' testCompile 'org.mockito:mockito-core:2.11.0' + testCompile 'org.slf4j:slf4j-simple:1.6.1' } jacocoTestReport { diff --git a/lib/src/main/java/oiccli/AES.java b/lib/src/main/java/oiccli/AES.java index 5900701..7b88210 100644 --- a/lib/src/main/java/oiccli/AES.java +++ b/lib/src/main/java/oiccli/AES.java @@ -1,8 +1,8 @@ package oiccli; -import org.junit.Assert; -import org.bouncycastle.util.encoders.Base64; import oiccli.exceptions.AESError; +import org.bouncycastle.util.encoders.Base64; +import org.junit.Assert; import java.util.Arrays; import java.util.List; diff --git a/lib/src/main/java/oiccli/AuthorizationResponse.java b/lib/src/main/java/oiccli/AuthorizationResponse.java index da75109..b559e75 100644 --- a/lib/src/main/java/oiccli/AuthorizationResponse.java +++ b/lib/src/main/java/oiccli/AuthorizationResponse.java @@ -19,20 +19,20 @@ public AuthorizationResponse() { } - public boolean verify(Map args) throws MissingRequiredAttribute { + public boolean verify(Map args) throws MissingRequiredAttribute { //super(AuthorizationResponse, self).verify(**kwargs) - if(this.contains("aud")) { - if(args.containsKey("clientId")) { - if(!this.getAudience().contains(args.get("clientId"))) { + if (this.contains("aud")) { + if (args.containsKey("clientId")) { + if (!this.getAudience().contains(args.get("clientId"))) { return false; } } } - if(this.contains("idToken")) { - Map argsTemp = new HashMap<>(); - for(String arg : Arrays.asList("key", "keyjar", "algs", "sender")) { + if (this.contains("idToken")) { + Map argsTemp = new HashMap<>(); + for (String arg : Arrays.asList("key", "keyjar", "algs", "sender")) { argsTemp.put(arg, args.get(arg)); } @@ -44,25 +44,25 @@ raise VerificationError("Could not verify id_token", idt) _alg = idt.jws_header["alg"] */ - String hFunction = "HS" + algorithm.substring(0,algorithm.length()-3); - if(this.getAccessToken() != null) { - if(this.idt.getAtHash() == null) { + String hFunction = "HS" + algorithm.substring(0, algorithm.length() - 3); + if (this.getAccessToken() != null) { + if (this.idt.getAtHash() == null) { throw new MissingRequiredAttribute("Missing at_hash property" + idToken.toString()); } - if(idt.getAtHash() != jws.leftHash(this.getAccessToken(), hFunction)) { + if (idt.getAtHash() != jws.leftHash(this.getAccessToken(), hFunction)) { throw new AtHashError( "Failed to verify access_token hash " + idt.toString()); } } - if(this.getCode() != null) { - if(this.idt.getCHash() == null) { + if (this.getCode() != null) { + if (this.idt.getCHash() == null) { throw new MissingRequiredAttribute("Missing cHash property" + idToken.toString()); } - if(idt.getCHash() != jws.leftHash(this.getCode(), hFunction)) { + if (idt.getCHash() != jws.leftHash(this.getCode(), hFunction)) { throw new CHashError("Failed to verify code hash " + idt.toString()); } } diff --git a/lib/src/main/java/oiccli/ErrorMessage.java b/lib/src/main/java/oiccli/ErrorMessage.java index c187954..44f788e 100644 --- a/lib/src/main/java/oiccli/ErrorMessage.java +++ b/lib/src/main/java/oiccli/ErrorMessage.java @@ -2,6 +2,6 @@ import com.auth0.jwt.creators.Message; -public class ErrorMessage extends Message{ +public class ErrorMessage extends Message { } diff --git a/lib/src/main/java/oiccli/HTTP/Http.java b/lib/src/main/java/oiccli/HTTP/Http.java index 414f056..f144305 100644 --- a/lib/src/main/java/oiccli/HTTP/Http.java +++ b/lib/src/main/java/oiccli/HTTP/Http.java @@ -42,6 +42,8 @@ public Map getCookies() { for (cookieJar.getCookies().) + { return cookiesMap; + } } } diff --git a/lib/src/main/java/oiccli/HTTP/Response.java b/lib/src/main/java/oiccli/HTTP/Response.java index 634f4bd..071254c 100644 --- a/lib/src/main/java/oiccli/HTTP/Response.java +++ b/lib/src/main/java/oiccli/HTTP/Response.java @@ -3,7 +3,12 @@ import com.auth0.jwt.creators.Message; import oiccli.StringUtil; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; public class Response { diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java index 668e0c8..3fb1f38 100644 --- a/lib/src/main/java/oiccli/Service.java +++ b/lib/src/main/java/oiccli/Service.java @@ -1,18 +1,26 @@ package oiccli; import com.auth0.jwt.creators.Message; +import javax.xml.ws.http.HTTPException; import oiccli.HTTP.Response; import oiccli.client_info.ClientInfo; -import oiccli.exceptions.*; +import oiccli.exceptions.MissingEndpoint; +import oiccli.exceptions.OicCliError; +import oiccli.exceptions.UnsupportedType; +import oiccli.exceptions.ValueError; +import oiccli.exceptions.WrongContentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.xml.ws.http.HTTPException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class Service { diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java index 0e70810..1d1b742 100644 --- a/lib/src/main/java/oiccli/State.java +++ b/lib/src/main/java/oiccli/State.java @@ -163,19 +163,19 @@ public Map getResponseArgs(String state, ABCMeta request, int no } public DefaultSynthStyle.StateInfo addResponse(AuthorizationResponse authorizationResponse, String state) throws UnknownState { - if(!StringUtil.isNotNullAndNotEmpty(state)) { + if (!StringUtil.isNotNullAndNotEmpty(state)) { state = authorizationResponse.getState(); } DefaultSynthStyle.StateInfo stateInfo = this.getState(state); - if(stateInfo == null) { + if (stateInfo == null) { throw new UnknownState(state); } stateInfo.setCode(authorizationResponse.getCode()); this.updateTokenInfo(stateInfo, authorizationResponse); - for(String claim : Arrays.asList("idToken", "refreshToken")) { + for (String claim : Arrays.asList("idToken", "refreshToken")) { stateInfo.setClaim(authorizationResponse.getClaim()); } diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java index de8df65..ebc696b 100644 --- a/lib/src/main/java/oiccli/Util.java +++ b/lib/src/main/java/oiccli/Util.java @@ -224,8 +224,8 @@ public static String verifyHeader(FakeResponse response, String bodyType) throws !matchTo(PLAIN_TEXT, contentType)) { throw new WrongContentType(contentType); } - } else if(bodyType.equals(TEXT)) { - if(!matchTo(PLAIN_TEXT, contentType) && !matchTo(HTML_TEXT, contentType)) { + } else if (bodyType.equals(TEXT)) { + if (!matchTo(PLAIN_TEXT, contentType) && !matchTo(HTML_TEXT, contentType)) { throw new WrongContentType("Content type: " + contentType); } } else { diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java index 38ae30a..e0d3c26 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java @@ -1,12 +1,9 @@ package oiccli.client_auth; import com.auth0.jwt.jwts.JWT; - import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import org.apache.commons.codec.binary.Base64; -import org.apache.commons.text.CharacterPredicates; -import org.apache.commons.text.RandomStringGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +30,7 @@ public Map> construct(Map cis, Clien httpArgs = new HashMap<>(); } - if(!httpArgs.containsKey("headers")) { + if (!httpArgs.containsKey("headers")) { httpArgs.put("headers", new HashMap()); } diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java index 04c07c7..df8947d 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java @@ -13,6 +13,7 @@ public static String chooseAlgorithm(String entity, Map args) th return JWSAuthenticationMethod.chooseAlgorithm(entity, args); } + @Override public Key getSigningKey(String algorithm, ClientInfo clientInfo) { return clientInfo.getKeyJar().getSigningKey(StringUtil.alg2keytype(algorithm), algorithm); } diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java index 9a7450e..dffce3f 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java @@ -1,7 +1,5 @@ package oiccli.client_auth; -import com.sun.security.ntlm.Client; - import java.util.Map; public class ClientSecretPost extends ClientSecretBasic { diff --git a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java index 9e71d4a..4080bc3 100644 --- a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java +++ b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java @@ -3,14 +3,11 @@ import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; - -import java.util.Arrays; -import java.util.HashMap; - import oiccli.exceptions.NoMatchingKey; import org.junit.Assert; -import static org.junit.Assert.assertTrue; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; diff --git a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java index 7aeb364..dae8193 100644 --- a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java +++ b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java @@ -13,10 +13,12 @@ public static String chooseAlgorithm(String entity, Map args) th return JWSAuthenticationMethod.chooseAlgorithm(entity, args); } + @Override public String chooseAlgorithm(Map args) throws AuthenticationFailure { return chooseAlgorithm("private_key_jwt", args); } + @Override public Key getSigningKey(String algorithm, ClientInfo clientInfo) { return clientInfo.getKeyJar().getSigningKey(StringUtil.alg2keytype(algorithm), "", algorithm); } diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java index 2bb590e..14ffa32 100644 --- a/lib/src/main/java/oiccli/client_info/ClientInfo.java +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -10,7 +10,11 @@ import org.slf4j.LoggerFactory; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ClientInfo { @@ -128,20 +132,20 @@ public ClientInfo(KeyJar keyjar, Map config, List events this.importKeys(config.get("keys")); - if(config.containsKey("keydefs")) { + if (config.containsKey("keydefs")) { this.keyJar = buildKeyJar(config.get("keydefs"), this.keyJar)[1]; } } - public void importKeys(Map>> keySpec) { - for(String key : keySpec.keySet()) { - if(key.equals("file")) { - Map> hMap = keySpec.get(key); - for(String hMapKey : hMap.keySet()) { - if(hMapKey.equals("rsa")) { + public void importKeys(Map>> keySpec) { + for (String key : keySpec.keySet()) { + if (key.equals("file")) { + Map> hMap = keySpec.get(key); + for (String hMapKey : hMap.keySet()) { + if (hMapKey.equals("rsa")) { Key key; KeyBundle keyBundle; - for(String file : hMap.get(hMapKey)) { + for (String file : hMap.get(hMapKey)) { key = new RSAKey(importPrivateRsaKeyFromFile(file), "sig"); keyBundle = new KeyBundle(); keyBundle.append(key); @@ -149,9 +153,9 @@ public void importKeys(Map>> keySpec) { } } } - } else if(key.equals("url")) { + } else if (key.equals("url")) { KeyBundle keyBundle; - for(String issuer : keySpec.keySet()) { + for (String issuer : keySpec.keySet()) { keyBundle = new KeyBundle(keySpec.get(issuer)); this.keyJar.addKb(keyBundle); } @@ -195,13 +199,17 @@ public String getClientSecret() { return cSecret; } - public Map> getKid() { return kid; } + public Map> getKid() { + return kid; + } public void setClientSecret(String cSecret) { this.cSecret = cSecret; } - public State getState() { return stateDb; } + public State getState() { + return stateDb; + } public void setCSecret(String secret) { if (secret == null) { @@ -312,7 +320,7 @@ public List generateRequestUris(String requestsDir) { public static List addCodeChallenge(ClientInfo clientInfo, String state) { Integer cvLength = (Integer) clientInfo.config.get("codeChallenge").get("length"); - if(cvLength == null) { + if (cvLength == null) { cvLength = 64; } @@ -347,6 +355,6 @@ public void setRegistrationExpires(String registrationExpires) { } public static Object getCodeVerifier(ClientInfo clientInfo, String state) throws ExpiredToken { - return clientInfo.getStateDb().getTokenInfo("state"+state).get("codeVerifier"); + return clientInfo.getStateDb().getTokenInfo("state" + state).get("codeVerifier"); } } diff --git a/lib/src/main/java/oiccli/exceptions/AESError.java b/lib/src/main/java/oiccli/exceptions/AESError.java index 84a6107..269cdb1 100644 --- a/lib/src/main/java/oiccli/exceptions/AESError.java +++ b/lib/src/main/java/oiccli/exceptions/AESError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class AESError extends Exception{ +public class AESError extends Exception { public AESError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/AtHashError.java b/lib/src/main/java/oiccli/exceptions/AtHashError.java index 09050e4..043ad7e 100644 --- a/lib/src/main/java/oiccli/exceptions/AtHashError.java +++ b/lib/src/main/java/oiccli/exceptions/AtHashError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class AtHashError extends Exception{ +public class AtHashError extends Exception { public AtHashError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java b/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java index e5239b5..da38213 100644 --- a/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java +++ b/lib/src/main/java/oiccli/exceptions/AuthenticationFailure.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class AuthenticationFailure extends Exception{ +public class AuthenticationFailure extends Exception { public AuthenticationFailure(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/CHashError.java b/lib/src/main/java/oiccli/exceptions/CHashError.java index af5ce6d..ade61e3 100644 --- a/lib/src/main/java/oiccli/exceptions/CHashError.java +++ b/lib/src/main/java/oiccli/exceptions/CHashError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class CHashError extends Exception{ +public class CHashError extends Exception { public CHashError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/ConfigurationError.java b/lib/src/main/java/oiccli/exceptions/ConfigurationError.java index 730d2d9..458e7ac 100644 --- a/lib/src/main/java/oiccli/exceptions/ConfigurationError.java +++ b/lib/src/main/java/oiccli/exceptions/ConfigurationError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class ConfigurationError extends Exception{ +public class ConfigurationError extends Exception { public ConfigurationError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/ExpiredToken.java b/lib/src/main/java/oiccli/exceptions/ExpiredToken.java index d57bfab..a86a473 100644 --- a/lib/src/main/java/oiccli/exceptions/ExpiredToken.java +++ b/lib/src/main/java/oiccli/exceptions/ExpiredToken.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class ExpiredToken extends Exception{ +public class ExpiredToken extends Exception { public ExpiredToken(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/MessageException.java b/lib/src/main/java/oiccli/exceptions/MessageException.java index c7bf36a..64bdfce 100644 --- a/lib/src/main/java/oiccli/exceptions/MessageException.java +++ b/lib/src/main/java/oiccli/exceptions/MessageException.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class MessageException extends Exception{ +public class MessageException extends Exception { public MessageException(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java b/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java index 0a7d747..5d945bc 100644 --- a/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java +++ b/lib/src/main/java/oiccli/exceptions/MissingEndpoint.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class MissingEndpoint extends Exception{ +public class MissingEndpoint extends Exception { public MissingEndpoint(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/MissingParameter.java b/lib/src/main/java/oiccli/exceptions/MissingParameter.java index 2207c4f..ec7e0e9 100644 --- a/lib/src/main/java/oiccli/exceptions/MissingParameter.java +++ b/lib/src/main/java/oiccli/exceptions/MissingParameter.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class MissingParameter extends Exception{ +public class MissingParameter extends Exception { public MissingParameter(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java b/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java index d6e1b82..661f797 100644 --- a/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java +++ b/lib/src/main/java/oiccli/exceptions/MissingRequiredAttribute.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class MissingRequiredAttribute extends Exception{ +public class MissingRequiredAttribute extends Exception { public MissingRequiredAttribute(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java b/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java index 5a265bf..a7277e0 100644 --- a/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java +++ b/lib/src/main/java/oiccli/exceptions/NoMatchingKey.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class NoMatchingKey extends Exception{ +public class NoMatchingKey extends Exception { public NoMatchingKey(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/OicCliError.java b/lib/src/main/java/oiccli/exceptions/OicCliError.java index f7a8fc5..93cc18d 100644 --- a/lib/src/main/java/oiccli/exceptions/OicCliError.java +++ b/lib/src/main/java/oiccli/exceptions/OicCliError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class OicCliError extends Exception{ +public class OicCliError extends Exception { public OicCliError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/OicMsgError.java b/lib/src/main/java/oiccli/exceptions/OicMsgError.java index 4c507c0..94629b5 100644 --- a/lib/src/main/java/oiccli/exceptions/OicMsgError.java +++ b/lib/src/main/java/oiccli/exceptions/OicMsgError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class OicMsgError extends Exception{ +public class OicMsgError extends Exception { public OicMsgError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/UnsupportedType.java b/lib/src/main/java/oiccli/exceptions/UnsupportedType.java index 57d12d5..9482405 100644 --- a/lib/src/main/java/oiccli/exceptions/UnsupportedType.java +++ b/lib/src/main/java/oiccli/exceptions/UnsupportedType.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class UnsupportedType extends Exception{ +public class UnsupportedType extends Exception { public UnsupportedType(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/ValueError.java b/lib/src/main/java/oiccli/exceptions/ValueError.java index 9301f3b..e548c67 100644 --- a/lib/src/main/java/oiccli/exceptions/ValueError.java +++ b/lib/src/main/java/oiccli/exceptions/ValueError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class ValueError extends Exception{ +public class ValueError extends Exception { public ValueError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/WebFingerError.java b/lib/src/main/java/oiccli/exceptions/WebFingerError.java index 768f1ba..d1e8813 100644 --- a/lib/src/main/java/oiccli/exceptions/WebFingerError.java +++ b/lib/src/main/java/oiccli/exceptions/WebFingerError.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class WebFingerError extends Exception{ +public class WebFingerError extends Exception { public WebFingerError(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/exceptions/WrongContentType.java b/lib/src/main/java/oiccli/exceptions/WrongContentType.java index eaeb01e..306aaf8 100644 --- a/lib/src/main/java/oiccli/exceptions/WrongContentType.java +++ b/lib/src/main/java/oiccli/exceptions/WrongContentType.java @@ -1,6 +1,6 @@ package oiccli.exceptions; -public class WrongContentType extends Exception{ +public class WrongContentType extends Exception { public WrongContentType(String message) { super(message); } diff --git a/lib/src/main/java/oiccli/service/Authorization.java b/lib/src/main/java/oiccli/service/Authorization.java index d50f37e..093e55a 100644 --- a/lib/src/main/java/oiccli/service/Authorization.java +++ b/lib/src/main/java/oiccli/service/Authorization.java @@ -32,7 +32,7 @@ public Authorization(Object httpLib, Object keyJar, Map clientAut public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) { if (requestArgs != null) { String responseType = (String) requestArgs.get("responseType"); - if(responseType == null) { + if (responseType == null) { requestArgs.put("responseType", clientInfo.getBehavior().get("responseTypes").get(0)); } @@ -68,7 +68,7 @@ public Authorization(Object httpLib, Object keyJar, Map clientAut requestArgs.put("responseMode", responseMode); } - if(!requestArgs.containsKey("state")) { + if (!requestArgs.containsKey("state")) { requestArgs.put("state", clientInfo.getStateDb().createState(clientInfo.getIssuer(), requestArgs)); } diff --git a/lib/src/main/java/oiccli/service/CheckID.java b/lib/src/main/java/oiccli/service/CheckID.java index 778cd78..b510b7e 100644 --- a/lib/src/main/java/oiccli/service/CheckID.java +++ b/lib/src/main/java/oiccli/service/CheckID.java @@ -3,8 +3,6 @@ import com.auth0.jwt.creators.Message; import oiccli.client_info.ClientInfo; import oiccli.exceptions.MissingParameter; -import oiccli.service.Service; -import oiccli.service.UserInfo; import java.util.Arrays; import java.util.HashMap; diff --git a/lib/src/main/java/oiccli/service/EndSession.java b/lib/src/main/java/oiccli/service/EndSession.java index 4e148ea..741b6f8 100644 --- a/lib/src/main/java/oiccli/service/EndSession.java +++ b/lib/src/main/java/oiccli/service/EndSession.java @@ -18,11 +18,11 @@ public class EndSession extends Service { private static String request = "endSession"; public EndSession(String httpLib, KeyJar keyJar, String clientAuthenticationMethod) { - super(httpLib,keyJar,clientAuthenticationMethod); + super(httpLib, keyJar, clientAuthenticationMethod); //self.pre_construct = [self.oic_pre_construct] } - public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) throws MissingParameter { + public List> oicPreConstruct(ClientInfo clientInfo, Map requestArgs, Map args) throws MissingParameter { requestArgs = UserInfo.setIdToken(clientInfo, requestArgs, args); return Arrays.asList(requestArgs, new HashMap()); } diff --git a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java index f07e743..2f1373b 100644 --- a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java +++ b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java @@ -6,7 +6,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; public class ProviderInfoDiscovery extends service.ProviderInfoDiscovery { private Message message; @@ -79,8 +84,8 @@ public static void matchPreferences(ClientInfo clientInfo, Map ava; - private Map>> cParams; - static final Map link = new HashMap() {{ - put("rel", new HashMap() {{ put("type", String.class); put("required", true); }}); - put("type", new HashMap() {{ put("type", String.class); put("required", false); }}); - put("href", new HashMap() {{ put("type", String.class); put("required", false); }}); - put("titles", new HashMap() {{ put("type", Map.class); put("required", false); }}); - put("properties", new HashMap() {{ put("type", Map.class); put("required", false); }}); + private Map ava; + private Map>> cParams; + static final Map link = new HashMap() {{ + put("rel", new HashMap() {{ + put("type", String.class); + put("required", true); + }}); + put("type", new HashMap() {{ + put("type", String.class); + put("required", false); + }}); + put("href", new HashMap() {{ + put("type", String.class); + put("required", false); + }}); + put("titles", new HashMap() {{ + put("type", Map.class); + put("required", false); + }}); + put("properties", new HashMap() {{ + put("type", Map.class); + put("required", false); + }}); }}; - public Base(Map hMap) { + public Base(Map hMap) { ava = new HashMap<>(); - if(hMap != null) { + if (hMap != null) { this.load(hMap); } cParams = new HashMap<>(); } public void setItem(String key, List value) { - HashMap> spec = this.cParams.get(key); - if(spec == null) { - spec = new HashMap>() {{ + HashMap> spec = this.cParams.get(key); + if (spec == null) { + spec = new HashMap>() {{ put("type", Arrays.asList(this.toString())); put("isRequired", Arrays.asList(false)); }}; @@ -37,21 +55,21 @@ public void setItem(String key, List value) { List types = spec.get("type"); Object t1, t2; - if(types != null && types.size() == 2) { + if (types != null && types.size() == 2) { t1 = types.get(0); t2 = types.get(1); } else { throw new IllegalArgumentException("'Type' should have returned 2 values"); } - if(t1.getClass().equals(List.class)) { + if (t1.getClass().equals(List.class)) { List result = new ArrayList<>(); - if(t2.equals(link)) { - for(String index : value) { + if (t2.equals(link)) { + for (String index : value) { result.add(link.get(index)); } } else { - for(String index : value) { + for (String index : value) { Assert.assertTrue(index instanceof t2); result.add(index); } @@ -60,15 +78,15 @@ public void setItem(String key, List value) { } } - public void load(Map> hMap) throws ValueError { - for(String key : this.cParams.keySet()) { - if(!hMap.containsKey(key) && cParams.get(key).get("required")) { + public void load(Map> hMap) throws ValueError { + for (String key : this.cParams.keySet()) { + if (!hMap.containsKey(key) && cParams.get(key).get("required")) { throw new ValueError("Required attribute " + key + " missing"); } } - for(String key : hMap.keySet()) { - if(!hMap.get(key).equals("") || !hMap.get(key).isEmpty()) { + for (String key : hMap.keySet()) { + if (!hMap.get(key).equals("") || !hMap.get(key).isEmpty()) { setItem(key, hMap.get(key)); } } @@ -77,7 +95,7 @@ public void load(Map> hMap) throws ValueError { public Map> dump() { Map> result = new HashMap<>(); List list = new ArrayList<>(); - for(String key : this.ava.keySet()) { + for (String key : this.ava.keySet()) { list = this.cParams.get(key).get("type"); if (list != null && list.size() == 2 && (list.get(0) instanceof List) && (list.get(1) instanceof Map)) { diff --git a/lib/src/main/java/oiccli/webfinger/JRD.java b/lib/src/main/java/oiccli/webfinger/JRD.java index f09cb69..f7ed17b 100644 --- a/lib/src/main/java/oiccli/webfinger/JRD.java +++ b/lib/src/main/java/oiccli/webfinger/JRD.java @@ -5,13 +5,28 @@ import java.util.List; import java.util.Map; -public class JRD extends Base{ - private static final Map cParam = new HashMap() {{ - put("expires", new HashMap() {{ put("type", String.class); put("required", false); }}); - put("subject", new HashMap() {{ put("type", String.class); put("required", false); }}); - put("aliases", new HashMap() {{ put("type", Arrays.asList(String.class, List.class)); put("required", false); }}); - put("properties", new HashMap() {{ put("type", Map.class); put("required", false); }}); - put("links", new HashMap() {{ put("type", Arrays.asList(List.class, Map.class)); put("required", false); }}); +public class JRD extends Base { + private static final Map cParam = new HashMap() {{ + put("expires", new HashMap() {{ + put("type", String.class); + put("required", false); + }}); + put("subject", new HashMap() {{ + put("type", String.class); + put("required", false); + }}); + put("aliases", new HashMap() {{ + put("type", Arrays.asList(String.class, List.class)); + put("required", false); + }}); + put("properties", new HashMap() {{ + put("type", Map.class); + put("required", false); + }}); + put("links", new HashMap() {{ + put("type", Arrays.asList(List.class, Map.class)); + put("required", false); + }}); }}; private int expDays; private int expSeconds; @@ -25,7 +40,7 @@ public JRD(Map hMap, int days, int seconds, int minutes, int hou } public JRD() { - this(null,0,0,0,0,0); + this(null, 0, 0, 0, 0, 0); } public void expiresIn(int days, int seconds, int minutes, int hours, int weeks) { @@ -42,7 +57,7 @@ public Map> export() { return result; } - public Map getcParam() { + public Map getcParam() { return cParam; } } diff --git a/lib/src/main/java/oiccli/webfinger/URINormalizer.java b/lib/src/main/java/oiccli/webfinger/URINormalizer.java index 9f8c13c..4b564aa 100644 --- a/lib/src/main/java/oiccli/webfinger/URINormalizer.java +++ b/lib/src/main/java/oiccli/webfinger/URINormalizer.java @@ -1,20 +1,18 @@ package oiccli.webfinger; -import org.junit.Assert; - public class URINormalizer { public boolean hasScheme(String path) { - if(path.contains("://")) { + if (path.contains("://")) { return true; } else { String authority = path.replace("/", "#") .replace("?", "#").split("#")[0]; String hostOrPort; - if(authority.contains(":")) { + if (authority.contains(":")) { hostOrPort = authority.split(":", 1)[1]; - if(hostOrPort.matches("^\\d+$")) { + if (hostOrPort.matches("^\\d+$")) { return false; } } else { @@ -27,18 +25,18 @@ public boolean hasScheme(String path) { public boolean isAccountSchemeAssumed(String path) { String[] arr; - if(path.contains("@")) { + if (path.contains("@")) { arr = path.split("@"); - String host = arr[arr.length-1]; + String host = arr[arr.length - 1]; return !(host.contains(":") || host.contains("/") || host.contains("?")); } else { return false; } } - + public String normalize(String path) { - if(!this.hasScheme(path)) { - if(this.isAccountSchemeAssumed(path)) { + if (!this.hasScheme(path)) { + if (this.isAccountSchemeAssumed(path)) { path = "acct:" + path; } else { path = "https://" + path; diff --git a/lib/src/main/java/oiccli/webfinger/WebFinger.java b/lib/src/main/java/oiccli/webfinger/WebFinger.java index a9e5130..da865eb 100644 --- a/lib/src/main/java/oiccli/webfinger/WebFinger.java +++ b/lib/src/main/java/oiccli/webfinger/WebFinger.java @@ -1,11 +1,7 @@ package oiccli.webfinger; -import com.google.common.base.Strings; -import com.sun.deploy.net.HttpResponse; -import oiccli.HTTP.Response; import oiccli.StringUtil; import oiccli.Tuple; -import oiccli.client_info.ClientInfo; import oiccli.exceptions.MessageException; import oiccli.exceptions.OicMsgError; import oiccli.exceptions.WebFingerError; @@ -16,14 +12,18 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class WebFinger { public String defaultRelt; public Object httpd; private JRD jrd; - private List> events; + private List> events; private static final String WF_URL = "https://%s/.well-known/webfinger"; final private static Logger logger = LoggerFactory.getLogger(WebFinger.class); private static final String OIC_ISSUER = "http://openid.net/specs/connect/1.0/issuer"; @@ -39,40 +39,42 @@ public String query(String resource, List rel) throws URISyntaxException resource = new URINormalizer().normalize(resource); List queryParamsTuple = new ArrayList<>(Arrays.asList(new Tuple("resource", resource))); - if(rel == null) { - if(StringUtil.isNotNullAndNotEmpty(this.defaultRelt)) { + if (rel == null) { + if (StringUtil.isNotNullAndNotEmpty(this.defaultRelt)) { queryParamsTuple.add(new Tuple("rel", this.defaultRelt)); } } else { - for(String index : rel) { + for (String index : rel) { queryParamsTuple.add(new Tuple("rel", index)); } } String host; - if(resource.startsWith("http")) { + if (resource.startsWith("http")) { URI uri = new URI(resource); host = uri.getHost(); int port = uri.getPort(); - if(port != -1) { + if (port != -1) { host += ":" + port; } - } else if(resource.startsWith("acct:")) { + } else if (resource.startsWith("acct:")) { String[] arr = resource.split("@"); - host = arr[arr.length-1]; + host = arr[arr.length - 1]; arr = host.replace("/", "#").replace("?", "#").split("#"); host = arr[0]; - } else if(resource.startsWith("device:")) { + } else if (resource.startsWith("device:")) { String[] arr = resource.split(":"); host = arr[1]; } else { throw new WebFingerError("Unknown schema"); } - + String queryParams = ""; - for(int i = 0; i < queryParamsTuple.size(); i++) { + for (int i = 0; + i < queryParamsTuple.size(); + i++) { queryParams += queryParamsTuple.get(i).getA() + "=" + queryParamsTuple.get(i).getB(); - if(i != queryParamsTuple.size()-1) { + if (i != queryParamsTuple.size() - 1) { queryParams += "&"; } } @@ -80,25 +82,25 @@ public String query(String resource, List rel) throws URISyntaxException return String.format(WF_URL, host) + "?" + URLEncoder.encode(queryParams); } - public static JRD load(Map item) { + public static JRD load(Map item) { return new JRD(json.loads(item)); } - public Map> httpArgs(JRD jrd) { - if(jrd == null) { - if(this.jrd != null) { + public Map> httpArgs(JRD jrd) { + if (jrd == null) { + if (this.jrd != null) { jrd = this.jrd; } else { return null; } } - Map hMap = new HashMap() {{ - put("Access-Control-Allow-Origin", "*"); - put("Content-Type", "application/json; charset=UTF-8"); + Map hMap = new HashMap() {{ + put("Access-Control-Allow-Origin", "*"); + put("Content-Type", "application/json; charset=UTF-8"); }}; - Map> headersAndBody = new HashMap<>(); + Map> headersAndBody = new HashMap<>(); headersAndBody.put("headers", hMap); headersAndBody.put("body", json.dumps(jrd.export())); @@ -155,10 +157,10 @@ public String discoveryQuery(String resource) throws URISyntaxException, WebFing public static Object linkDeser(Object val, String sFormat) { - if(val instanceof Map) { + if (val instanceof Map) { return val; - } else if(sFormat.equals("dict") || sFormat.equals("json")) { - if(!(val instanceof String)) { + } else if (sFormat.equals("dict") || sFormat.equals("json")) { + if (!(val instanceof String)) { val = json.dumps(val); sFormat = "json"; } @@ -169,9 +171,9 @@ public static Object linkDeser(Object val, String sFormat) { public static Object messageSer(Object inst, String sFormat, int lev) throws MessageException, OicMsgError { Object res; - if(sFormat.equals("urlencoded") || sFormat.equals("json")) { - if(inst instanceof Map) { - if(sFormat.equals("json")) { + if (sFormat.equals("urlencoded") || sFormat.equals("json")) { + if (inst instanceof Map) { + if (sFormat.equals("json")) { res = json.dumps(inst); } else { res = Base64.encodeBase64URLSafe() @@ -182,10 +184,10 @@ public static Object messageSer(Object inst, String sFormat, int lev) throws Mes else { res = inst; } - } else if(sFormat.equals("dict")) { - if(inst instanceof Map) { + } else if (sFormat.equals("dict")) { + if (inst instanceof Map) { res = inst.serialize(sFormat, lev); - } else if(inst instanceof String) { + } else if (inst instanceof String) { res = inst; } else { throw new MessageException("Wrong type: " + inst.getClass()); From 1c23f4e9d4868eac05a49f0d41829a58c91b6c33 Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Wed, 24 Jan 2018 14:29:11 -0800 Subject: [PATCH 06/10] Oicclient --- lib/src/main/java/oiccli/AES.java | 21 +++++++++++-------- .../java/oiccli/AuthorizationResponse.java | 4 ---- lib/src/main/java/oiccli/HTTP/Response.java | 6 +++--- lib/src/main/java/oiccli/Service.java | 17 ++++++++------- lib/src/main/java/oiccli/State.java | 5 +++-- lib/src/main/java/oiccli/StringUtil.java | 4 ---- lib/src/main/java/oiccli/Util.java | 11 +++++----- .../java/oiccli/client_info/ClientInfo.java | 3 ++- .../main/java/oiccli/webfinger/WebFinger.java | 3 ++- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/lib/src/main/java/oiccli/AES.java b/lib/src/main/java/oiccli/AES.java index 7b88210..9c4ebf3 100644 --- a/lib/src/main/java/oiccli/AES.java +++ b/lib/src/main/java/oiccli/AES.java @@ -10,6 +10,9 @@ public class AES { private static final int BLOCK_SIZE = 16; + private static final String AES_ALGORITHM = "aes_128_cbc"; + private static final String PADDING_7 = "PKCS#7"; + private static final String PADDING_5 = "PKCS#5"; private byte[] key; private int mode; private byte[] iv; @@ -31,7 +34,7 @@ public static List buildCipher(byte[] key, byte[] iv, String alg) if (iv == null) { } else { - Assert.assertTrue(key.length == 16); //AES.blockSize + Assert.assertTrue(key.length == BLOCK_SIZE); //AES.blockSize } int bits = Integer.parseInt(algArr[1]); @@ -55,7 +58,7 @@ raise AESError("Unsupported chaining mode")*/ } public static List buildCipher(byte[] key, byte[] iv) throws AESError { - buildCipher(key, iv, "aes_128_cbc"); + buildCipher(key, iv, AES_ALGORITHM); return null; } @@ -63,9 +66,9 @@ public static void encrypt(byte[] key, String msg, byte[] iv, String alg, String boolean shouldBase64Encrypt, int blockSize) { int blockSizeLocal; - if (padding.equals("PKCS#7")) { + if (padding.equals(PADDING_7)) { blockSizeLocal = blockSize; - } else if (padding.equals("PKCS#5")) { + } else if (padding.equals(PADDING_5)) { blockSizeLocal = 8; } else { blockSizeLocal = 0; @@ -91,7 +94,7 @@ public static void encrypt(byte[] key, String msg, byte[] iv, String alg, String } public static void encrypt(byte[] key, String msg) { - return encrypt(key, msg, null, "aes_128_cbc", "PKCS#7", true, BLOCK_SIZE); + return encrypt(key, msg, null, AES_ALGORITHM, PADDING_7, true, BLOCK_SIZE); } public static byte[] decrypt(byte[] key, String msg, byte[] iv, String padding, boolean shouldBase64Decrypt) throws AESError { @@ -102,16 +105,16 @@ public static byte[] decrypt(byte[] key, String msg, byte[] iv, String padding, data = msg.getBytes(); } - byte[] ivByteArr = Arrays.copyOfRange(data, 0, 16); + byte[] ivByteArr = Arrays.copyOfRange(data, 0, BLOCK_SIZE); if (iv != null) { Assert.assertEquals(iv, ivByteArr); } List cipherList = buildCipher(key, iv); //insert python code byte[] decrpytArr = cipher.decrypt(data); - byte[] res = Arrays.copyOfRange(decrpytArr, 16, decrpytArr.length); + byte[] res = Arrays.copyOfRange(decrpytArr, BLOCK_SIZE, decrpytArr.length); - if (padding.equals("PKCS#5") || padding.equals("PKCS#7")) { + if (padding.equals(PADDING_5) || padding.equals(PADDING_7)) { res = Arrays.copyOfRange(res, 0, res[res.length - 1]); } @@ -119,7 +122,7 @@ public static byte[] decrypt(byte[] key, String msg, byte[] iv, String padding, } public static void decrypt(byte[] key, String msg, byte[] iv) { - return decrypt(key, msg, null, "PKCS#7", true); + return decrypt(key, msg, null, PADDING_7, true); } public void addAssociatedData(String data) { diff --git a/lib/src/main/java/oiccli/AuthorizationResponse.java b/lib/src/main/java/oiccli/AuthorizationResponse.java index b559e75..19df641 100644 --- a/lib/src/main/java/oiccli/AuthorizationResponse.java +++ b/lib/src/main/java/oiccli/AuthorizationResponse.java @@ -15,10 +15,6 @@ public class AuthorizationResponse { private String tokenType; private String idToken; - public AuthorizationResponse() { - - } - public boolean verify(Map args) throws MissingRequiredAttribute { //super(AuthorizationResponse, self).verify(**kwargs) diff --git a/lib/src/main/java/oiccli/HTTP/Response.java b/lib/src/main/java/oiccli/HTTP/Response.java index 071254c..eaf17ed 100644 --- a/lib/src/main/java/oiccli/HTTP/Response.java +++ b/lib/src/main/java/oiccli/HTTP/Response.java @@ -1,6 +1,7 @@ package oiccli.HTTP; import com.auth0.jwt.creators.Message; +import com.google.common.base.Strings; import oiccli.StringUtil; import java.util.ArrayList; @@ -43,7 +44,7 @@ public Response(Message message, Map args) { } private List getResponse(String message, Map args) { - if (StringUtil.isNotNullAndNotEmpty(message)) { + if (!Strings.isNullOrEmpty(message)) { if (message.contains("", "</script>"); @@ -52,7 +53,7 @@ private List getResponse(String message, Map args) { if (this.template != null) { for (Map hMap : headers) { - if (hMap.containsKey("Content-type") && hMap.get("Content-type").equals("application/json")) { + if ("application/json".equals(hMap.get("Content-type"))) { return Arrays.asList(message); } else { //return [str(self.template % message).encode("utf-8")] @@ -102,7 +103,6 @@ public List cTypes() { if (((String) pair.getKey()).equals("Content-type")) { cTypes.add((String) pair.getValue()); } - it.remove(); } } } diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java index 3fb1f38..c19873d 100644 --- a/lib/src/main/java/oiccli/Service.java +++ b/lib/src/main/java/oiccli/Service.java @@ -1,6 +1,7 @@ package oiccli; import com.auth0.jwt.creators.Message; +import com.google.common.base.Strings; import javax.xml.ws.http.HTTPException; import oiccli.HTTP.Response; import oiccli.client_info.ClientInfo; @@ -177,7 +178,7 @@ public String getEndpoint(Map args) throws MissingEndpoint { if (uri != null) { args.remove("endpoint"); } else { - if (StringUtil.isNotNullAndNotEmpty(this.endpoint)) { + if (!Strings.isNullOrEmpty(endpoint)) { uri = this.endpoint; } else { throw new MissingEndpoint("No endpoint specified"); @@ -209,7 +210,7 @@ public Map initAuthenticationMethod(Message cis, ClientInfo clie httpArgs = new HashMap<>(); } - if (StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { + if (!Strings.isNullOrEmpty(authenticationMethod)) { //return this.client_authn_method[authn_method]().construct( // cis, cli_info, request_args, http_args, **kwargs); } else { @@ -242,7 +243,7 @@ public Map requestInfo(ClientInfo clientInfo, String method, Map cis.setLax(lax); Map hArg = new HashMap<>(); - if (StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { + if (!Strings.isNullOrEmpty(authenticationMethod)) { hArg = this.initAuthenticationMethod(cis, clientInfo, authenticationMethod, requestArgs, args); } @@ -279,13 +280,13 @@ public Map updateHttpArgs(Map httpArgs, Map doRequestInit(ClientInfo clientInfo, String bodyType, String method, String authenticationMethod, Map requestArgs, Map httpArgs, Map args) throws NoSuchFieldException, IllegalAccessException, MissingEndpoint, UnsupportedEncodingException, UnsupportedType { - if (!StringUtil.isNotNullAndNotEmpty(method)) { + if (Strings.isNullOrEmpty(method)) { method = this.httpMethod; } - if (!StringUtil.isNotNullAndNotEmpty(authenticationMethod)) { + if (Strings.isNullOrEmpty(authenticationMethod)) { authenticationMethod = this.defaultAuthenticationMethod; } - if (!StringUtil.isNotNullAndNotEmpty(bodyType)) { + if (Strings.isNullOrEmpty(bodyType)) { bodyType = this.bodyType; } @@ -302,7 +303,7 @@ public String getUrlInfo(String info) throws URISyntaxException { fragment = uri.getFragment(); } - if (StringUtil.isNotNullAndNotEmpty(query)) { + if (!Strings.isNullOrEmpty(query)) { return query; } else { return fragment; @@ -388,7 +389,7 @@ public ErrorResponse parseErrorMessage(Response response, String bodyType) { } public String getValueType(FakeResponse response, String bodyType) throws WrongContentType, ValueError { - if (StringUtil.isNotNullAndNotEmpty(bodyType)) { + if (!Strings.isNullOrEmpty(bodyType)) { return Util.verifyHeader(response, bodyType); } else { return "urlencoded"; diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java index 1d1b742..fe1c65f 100644 --- a/lib/src/main/java/oiccli/State.java +++ b/lib/src/main/java/oiccli/State.java @@ -1,5 +1,6 @@ package oiccli; +import com.google.common.base.Strings; import oiccli.exceptions.ExpiredToken; import oiccli.exceptions.UnknownState; import sun.swing.plaf.synth.DefaultSynthStyle; @@ -17,7 +18,7 @@ public class State { public State(String clientId, Database db, String dbName, int lifetime) { this.clientId = clientId; if (db == null) { - if (StringUtil.isNotNullAndNotEmpty(dbName)) { + if (!Strings.isNullOrEmpty(dbName)) { this.db = shelve.open(dbName, true); } else { this.db = new Database(); @@ -163,7 +164,7 @@ public Map getResponseArgs(String state, ABCMeta request, int no } public DefaultSynthStyle.StateInfo addResponse(AuthorizationResponse authorizationResponse, String state) throws UnknownState { - if (!StringUtil.isNotNullAndNotEmpty(state)) { + if (Strings.isNullOrEmpty(state)) { state = authorizationResponse.getState(); } diff --git a/lib/src/main/java/oiccli/StringUtil.java b/lib/src/main/java/oiccli/StringUtil.java index 02bbf6f..d9a8f6b 100644 --- a/lib/src/main/java/oiccli/StringUtil.java +++ b/lib/src/main/java/oiccli/StringUtil.java @@ -25,8 +25,4 @@ public static String alg2keytype(String algorithm) { return null; } } - - public static boolean isNotNullAndNotEmpty(String s) { - return s != null && !s.isEmpty(); - } } diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java index ebc696b..512633b 100644 --- a/lib/src/main/java/oiccli/Util.java +++ b/lib/src/main/java/oiccli/Util.java @@ -1,6 +1,7 @@ package oiccli; import com.auth0.jwt.creators.Message; +import com.google.common.base.Strings; import oiccli.exceptions.UnsupportedType; import oiccli.exceptions.ValueError; import oiccli.exceptions.WrongContentType; @@ -130,14 +131,14 @@ public static void setCookie(CookieJar cookieJar, Map cookieMap) failedAttribute = attribute; if (attributes.containsKey(attribute)) { morselValue = morsel.get(attribute); - if (StringUtil.isNotNullAndNotEmpty(morselValue)) { + if (!Strings.isNullOrEmpty(morselValue)) { if (attribute.equals("expires")) { attributesCopy.put(attribute, dateToTime(morselValue)); } else { attributesCopy.put(attribute, morselValue); } } else if (attribute.equals("maxAge")) { - if (StringUtil.isNotNullAndNotEmpty(morselValue)) { + if (!Strings.isNullOrEmpty(morselValue)) { attributesCopy.put("expires", dateToTime(morselValue)); } } @@ -154,7 +155,7 @@ public static void setCookie(CookieJar cookieJar, Map cookieMap) } } - if (attributesCopy.get("domain") instanceof String && StringUtil.isNotNullAndNotEmpty((String) attributesCopy.get("domain")) && ((String) attributesCopy.get("domain")).startsWith(".")) { + if (attributesCopy.get("domain") instanceof String && !Strings.isNullOrEmpty((String) attributesCopy.get("domain")) && ((String) attributesCopy.get("domain")).startsWith(".")) { attributesCopy.put("domainInitialDot", true); } @@ -189,8 +190,8 @@ public static String verifyHeader(FakeResponse response, String bodyType) throws logger.debug("Response txt: " + response.getText().toString()); String contentType = response.getHeaders().getContentType(); - if (!StringUtil.isNotNullAndNotEmpty(contentType)) { - if (StringUtil.isNotNullAndNotEmpty(bodyType)) { + if (Strings.isNullOrEmpty(contentType)) { + if (!Strings.isNullOrEmpty(bodyType)) { return bodyType; } else { return "txt"; diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java index 14ffa32..79adf47 100644 --- a/lib/src/main/java/oiccli/client_info/ClientInfo.java +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -1,5 +1,6 @@ package oiccli.client_info; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.sun.org.apache.xml.internal.security.utils.Base64; import oiccli.State; @@ -112,7 +113,7 @@ public ClientInfo(KeyJar keyjar, Map config, List events } } - if (StringUtil.isNotNullAndNotEmpty(requestsDir)) { + if (!Strings.isNullOrEmpty(requestsDir)) { File file = new File(requestsDir); if (!file.isDirectory()) { try { diff --git a/lib/src/main/java/oiccli/webfinger/WebFinger.java b/lib/src/main/java/oiccli/webfinger/WebFinger.java index da865eb..607814a 100644 --- a/lib/src/main/java/oiccli/webfinger/WebFinger.java +++ b/lib/src/main/java/oiccli/webfinger/WebFinger.java @@ -1,5 +1,6 @@ package oiccli.webfinger; +import com.google.common.base.Strings; import oiccli.StringUtil; import oiccli.Tuple; import oiccli.exceptions.MessageException; @@ -40,7 +41,7 @@ public String query(String resource, List rel) throws URISyntaxException List queryParamsTuple = new ArrayList<>(Arrays.asList(new Tuple("resource", resource))); if (rel == null) { - if (StringUtil.isNotNullAndNotEmpty(this.defaultRelt)) { + if (!Strings.isNullOrEmpty(this.defaultRelt)) { queryParamsTuple.add(new Tuple("rel", this.defaultRelt)); } } else { From 838866101d0a43276372b4ddc9f1a33e42c2332c Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Thu, 25 Jan 2018 15:10:46 -0800 Subject: [PATCH 07/10] Import reorder --- lib/src/main/java/oiccli/AES.java | 5 ++--- .../java/oiccli/AuthorizationResponse.java | 7 +++---- lib/src/main/java/oiccli/HTTP/Response.java | 2 -- lib/src/main/java/oiccli/Service.java | 19 +++++++++---------- lib/src/main/java/oiccli/State.java | 7 +++---- lib/src/main/java/oiccli/Util.java | 11 +++++------ .../java/oiccli/client_auth/BearerBody.java | 9 ++++----- .../java/oiccli/client_auth/BearerHeader.java | 3 +-- .../oiccli/client_auth/ClientSecretBasic.java | 7 +++---- .../oiccli/client_auth/ClientSecretJwt.java | 5 ++--- .../client_auth/JWSAuthenticationMethod.java | 9 ++++----- .../oiccli/client_auth/PrivateKeyJwt.java | 5 ++--- .../java/oiccli/client_info/ClientInfo.java | 13 ++++++------- .../main/java/oiccli/service/AccessToken.java | 5 ++--- .../java/oiccli/service/Authorization.java | 7 +++---- lib/src/main/java/oiccli/service/CheckID.java | 5 ++--- .../java/oiccli/service/CheckSession.java | 5 ++--- .../main/java/oiccli/service/EndSession.java | 5 ++--- .../oiccli/service/ProviderInfoDiscovery.java | 9 ++++----- .../java/oiccli/service/Registration.java | 3 +-- .../main/java/oiccli/service/UserInfo.java | 9 ++++----- lib/src/main/java/oiccli/webfinger/Base.java | 5 ++--- .../main/java/oiccli/webfinger/WebFinger.java | 16 +++++++--------- 23 files changed, 73 insertions(+), 98 deletions(-) diff --git a/lib/src/main/java/oiccli/AES.java b/lib/src/main/java/oiccli/AES.java index 9c4ebf3..4f93502 100644 --- a/lib/src/main/java/oiccli/AES.java +++ b/lib/src/main/java/oiccli/AES.java @@ -1,12 +1,11 @@ package oiccli; +import java.util.Arrays; +import java.util.List; import oiccli.exceptions.AESError; import org.bouncycastle.util.encoders.Base64; import org.junit.Assert; -import java.util.Arrays; -import java.util.List; - public class AES { private static final int BLOCK_SIZE = 16; diff --git a/lib/src/main/java/oiccli/AuthorizationResponse.java b/lib/src/main/java/oiccli/AuthorizationResponse.java index 19df641..53add1e 100644 --- a/lib/src/main/java/oiccli/AuthorizationResponse.java +++ b/lib/src/main/java/oiccli/AuthorizationResponse.java @@ -1,12 +1,11 @@ package oiccli; -import oiccli.exceptions.AtHashError; -import oiccli.exceptions.CHashError; -import oiccli.exceptions.MissingRequiredAttribute; - import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import oiccli.exceptions.AtHashError; +import oiccli.exceptions.CHashError; +import oiccli.exceptions.MissingRequiredAttribute; public class AuthorizationResponse { diff --git a/lib/src/main/java/oiccli/HTTP/Response.java b/lib/src/main/java/oiccli/HTTP/Response.java index eaf17ed..5402c71 100644 --- a/lib/src/main/java/oiccli/HTTP/Response.java +++ b/lib/src/main/java/oiccli/HTTP/Response.java @@ -2,8 +2,6 @@ import com.auth0.jwt.creators.Message; import com.google.common.base.Strings; -import oiccli.StringUtil; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java index c19873d..c9406b3 100644 --- a/lib/src/main/java/oiccli/Service.java +++ b/lib/src/main/java/oiccli/Service.java @@ -2,6 +2,15 @@ import com.auth0.jwt.creators.Message; import com.google.common.base.Strings; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.text.ParseException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.xml.ws.http.HTTPException; import oiccli.HTTP.Response; import oiccli.client_info.ClientInfo; @@ -13,16 +22,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; -import java.text.ParseException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class Service { private final static Logger logger = LoggerFactory.getLogger(Service.class); diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java index fe1c65f..93e008a 100644 --- a/lib/src/main/java/oiccli/State.java +++ b/lib/src/main/java/oiccli/State.java @@ -1,13 +1,12 @@ package oiccli; import com.google.common.base.Strings; -import oiccli.exceptions.ExpiredToken; -import oiccli.exceptions.UnknownState; -import sun.swing.plaf.synth.DefaultSynthStyle; - import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import oiccli.exceptions.ExpiredToken; +import oiccli.exceptions.UnknownState; +import sun.swing.plaf.synth.DefaultSynthStyle; public class State { diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java index 512633b..4ef8f42 100644 --- a/lib/src/main/java/oiccli/Util.java +++ b/lib/src/main/java/oiccli/Util.java @@ -2,12 +2,6 @@ import com.auth0.jwt.creators.Message; import com.google.common.base.Strings; -import oiccli.exceptions.UnsupportedType; -import oiccli.exceptions.ValueError; -import oiccli.exceptions.WrongContentType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.UnsupportedEncodingException; import java.text.DateFormat; import java.text.ParseException; @@ -16,6 +10,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.exceptions.UnsupportedType; +import oiccli.exceptions.ValueError; +import oiccli.exceptions.WrongContentType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Util { diff --git a/lib/src/main/java/oiccli/client_auth/BearerBody.java b/lib/src/main/java/oiccli/client_auth/BearerBody.java index ae778e0..e8d23ef 100644 --- a/lib/src/main/java/oiccli/client_auth/BearerBody.java +++ b/lib/src/main/java/oiccli/client_auth/BearerBody.java @@ -1,15 +1,14 @@ package oiccli.client_auth; import com.auth0.jwt.jwts.JWT; -import oiccli.State; -import oiccli.StringUtil; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.AuthenticationFailure; - import java.security.Key; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.State; +import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.AuthenticationFailure; public class BearerBody { diff --git a/lib/src/main/java/oiccli/client_auth/BearerHeader.java b/lib/src/main/java/oiccli/client_auth/BearerHeader.java index 67dd981..9a27c4c 100644 --- a/lib/src/main/java/oiccli/client_auth/BearerHeader.java +++ b/lib/src/main/java/oiccli/client_auth/BearerHeader.java @@ -1,9 +1,8 @@ package oiccli.client_auth; -import oiccli.client_info.ClientInfo; - import java.util.HashMap; import java.util.Map; +import oiccli.client_info.ClientInfo; public class BearerHeader { diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java index e0d3c26..cec0542 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java @@ -1,16 +1,15 @@ package oiccli.client_auth; import com.auth0.jwt.jwts.JWT; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class ClientSecretBasic extends ClientAuthenticationMethod { private final static Logger logger = LoggerFactory.getLogger(ClientSecretBasic.class); diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java index df8947d..099a3df 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretJwt.java @@ -1,12 +1,11 @@ package oiccli.client_auth; +import java.security.Key; +import java.util.Map; import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; -import java.security.Key; -import java.util.Map; - public class ClientSecretJwt extends JWSAuthenticationMethod { public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { diff --git a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java index 4080bc3..686e0d7 100644 --- a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java +++ b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java @@ -1,16 +1,15 @@ package oiccli.client_auth; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; import oiccli.exceptions.NoMatchingKey; import org.junit.Assert; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class JWSAuthenticationMethod extends ClientAuthenticationMethod { private static final Map DEF_SIGN_ALG = new HashMap() {{ diff --git a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java index dae8193..8ca47f3 100644 --- a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java +++ b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java @@ -1,12 +1,11 @@ package oiccli.client_auth; +import java.security.Key; +import java.util.Map; import oiccli.StringUtil; import oiccli.client_info.ClientInfo; import oiccli.exceptions.AuthenticationFailure; -import java.security.Key; -import java.util.Map; - public class PrivateKeyJwt extends JWSAuthenticationMethod { public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java index 79adf47..a2af899 100644 --- a/lib/src/main/java/oiccli/client_info/ClientInfo.java +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -3,19 +3,18 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.sun.org.apache.xml.internal.security.utils.Base64; -import oiccli.State; -import oiccli.StringUtil; -import oiccli.exceptions.ExpiredToken; -import org.junit.Assert; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.State; +import oiccli.StringUtil; +import oiccli.exceptions.ExpiredToken; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ClientInfo { diff --git a/lib/src/main/java/oiccli/service/AccessToken.java b/lib/src/main/java/oiccli/service/AccessToken.java index 70f411c..bbbde11 100644 --- a/lib/src/main/java/oiccli/service/AccessToken.java +++ b/lib/src/main/java/oiccli/service/AccessToken.java @@ -1,13 +1,12 @@ package oiccli.service; +import java.util.Arrays; +import java.util.Map; import oiccli.AuthorizationResponse; import oiccli.client_info.ClientInfo; import oiccli.exceptions.ParameterError; import oiccli.exceptions.UnknownState; -import java.util.Arrays; -import java.util.Map; - public class AccessToken extends service.AccessToken { private AccessTokenRequest accessTokenRequest; private AccessTokenResponse accessTokenResponse; diff --git a/lib/src/main/java/oiccli/service/Authorization.java b/lib/src/main/java/oiccli/service/Authorization.java index 093e55a..aef6c8a 100644 --- a/lib/src/main/java/oiccli/service/Authorization.java +++ b/lib/src/main/java/oiccli/service/Authorization.java @@ -1,9 +1,5 @@ package oiccli.service; -import oiccli.AuthorizationResponse; -import oiccli.StringUtil; -import oiccli.client_info.ClientInfo; - import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; @@ -11,6 +7,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.AuthorizationResponse; +import oiccli.StringUtil; +import oiccli.client_info.ClientInfo; public class Authorization extends service.Authorization { diff --git a/lib/src/main/java/oiccli/service/CheckID.java b/lib/src/main/java/oiccli/service/CheckID.java index b510b7e..f569f2c 100644 --- a/lib/src/main/java/oiccli/service/CheckID.java +++ b/lib/src/main/java/oiccli/service/CheckID.java @@ -1,13 +1,12 @@ package oiccli.service; import com.auth0.jwt.creators.Message; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.MissingParameter; - import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; public class CheckID extends Service { private static CheckIDRequest checkIDRequest; diff --git a/lib/src/main/java/oiccli/service/CheckSession.java b/lib/src/main/java/oiccli/service/CheckSession.java index 06d7617..d22ef11 100644 --- a/lib/src/main/java/oiccli/service/CheckSession.java +++ b/lib/src/main/java/oiccli/service/CheckSession.java @@ -1,13 +1,12 @@ package oiccli.service; import com.auth0.jwt.creators.Message; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.MissingParameter; - import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; public class CheckSession extends Service { private static CheckSessionRequest checkSessionRequest; diff --git a/lib/src/main/java/oiccli/service/EndSession.java b/lib/src/main/java/oiccli/service/EndSession.java index 741b6f8..29afe09 100644 --- a/lib/src/main/java/oiccli/service/EndSession.java +++ b/lib/src/main/java/oiccli/service/EndSession.java @@ -1,13 +1,12 @@ package oiccli.service; import com.auth0.jwt.creators.Message; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.MissingParameter; - import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; public class EndSession extends Service { private static EndSessionRequest endSessionRequest; diff --git a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java index 2f1373b..5854d24 100644 --- a/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java +++ b/lib/src/main/java/oiccli/service/ProviderInfoDiscovery.java @@ -1,17 +1,16 @@ package oiccli.service; import com.auth0.jwt.creators.Message; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.ConfigurationError; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.ConfigurationError; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ProviderInfoDiscovery extends service.ProviderInfoDiscovery { private Message message; diff --git a/lib/src/main/java/oiccli/service/Registration.java b/lib/src/main/java/oiccli/service/Registration.java index 4bbfe75..9fd73bb 100644 --- a/lib/src/main/java/oiccli/service/Registration.java +++ b/lib/src/main/java/oiccli/service/Registration.java @@ -1,11 +1,10 @@ package oiccli.service; -import oiccli.client_info.ClientInfo; - import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.client_info.ClientInfo; public class Registration extends Service { diff --git a/lib/src/main/java/oiccli/service/UserInfo.java b/lib/src/main/java/oiccli/service/UserInfo.java index e1b19a8..cec3af3 100644 --- a/lib/src/main/java/oiccli/service/UserInfo.java +++ b/lib/src/main/java/oiccli/service/UserInfo.java @@ -1,11 +1,6 @@ package oiccli.service; import com.auth0.jwt.creators.Message; -import oiccli.client_info.ClientInfo; -import oiccli.exceptions.MissingParameter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -14,6 +9,10 @@ import java.util.List; import java.util.Map; import java.util.Set; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingParameter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class UserInfo extends Service { private Message message; diff --git a/lib/src/main/java/oiccli/webfinger/Base.java b/lib/src/main/java/oiccli/webfinger/Base.java index 9f7156f..a8a64cb 100644 --- a/lib/src/main/java/oiccli/webfinger/Base.java +++ b/lib/src/main/java/oiccli/webfinger/Base.java @@ -1,13 +1,12 @@ package oiccli.webfinger; -import oiccli.exceptions.ValueError; -import org.junit.Assert; - import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.exceptions.ValueError; +import org.junit.Assert; public class Base { diff --git a/lib/src/main/java/oiccli/webfinger/WebFinger.java b/lib/src/main/java/oiccli/webfinger/WebFinger.java index 607814a..b55cecc 100644 --- a/lib/src/main/java/oiccli/webfinger/WebFinger.java +++ b/lib/src/main/java/oiccli/webfinger/WebFinger.java @@ -1,15 +1,6 @@ package oiccli.webfinger; import com.google.common.base.Strings; -import oiccli.StringUtil; -import oiccli.Tuple; -import oiccli.exceptions.MessageException; -import oiccli.exceptions.OicMsgError; -import oiccli.exceptions.WebFingerError; -import org.apache.commons.codec.binary.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; @@ -18,6 +9,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import oiccli.Tuple; +import oiccli.exceptions.MessageException; +import oiccli.exceptions.OicMsgError; +import oiccli.exceptions.WebFingerError; +import org.apache.commons.codec.binary.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class WebFinger { From 8e538b954ae35a05f5821673fe4d3ab84bb17656 Mon Sep 17 00:00:00 2001 From: Justin Dahmubed Date: Tue, 30 Jan 2018 09:40:56 -0800 Subject: [PATCH 08/10] Oicclient cleanup --- .../java/com/auth0/jwt/creators/Message.java | 9 +- lib/src/main/java/oiccli/FakeResponse.java | 17 ++ lib/src/main/java/oiccli/HTTP/CookieJar.java | 4 + .../main/java/oiccli/HTTP/FileCookieJar.java | 4 + lib/src/main/java/oiccli/HTTP/Http.java | 5 +- lib/src/main/java/oiccli/Service.java | 58 +++++-- lib/src/main/java/oiccli/State.java | 2 +- lib/src/main/java/oiccli/Util.java | 7 +- lib/src/main/java/oiccli/Utils.java | 80 +++++++++ .../java/oiccli/client_auth/BearerHeader.java | 13 +- .../oiccli/client_auth/ClientSecretBasic.java | 24 +-- .../oiccli/client_auth/ClientSecretPost.java | 14 +- .../client_auth/JWSAuthenticationMethod.java | 27 +-- .../oiccli/client_auth/PrivateKeyJwt.java | 16 ++ .../java/oiccli/client_info/ClientInfo.java | 161 +++++++++++------- .../main/java/oiccli/client_info/Usage.java | 5 - .../java/oiccli/service/Authorization.java | 24 ++- .../java/oiccli/service/Registration.java | 17 +- lib/src/main/java/oiccli/webfinger/JRD.java | 7 +- .../java/oiccli/webfinger/URINormalizer.java | 2 +- .../main/java/oiccli/webfinger/WebFinger.java | 62 +------ 21 files changed, 345 insertions(+), 213 deletions(-) create mode 100644 lib/src/main/java/oiccli/FakeResponse.java create mode 100644 lib/src/main/java/oiccli/HTTP/CookieJar.java create mode 100644 lib/src/main/java/oiccli/HTTP/FileCookieJar.java create mode 100644 lib/src/main/java/oiccli/Utils.java delete mode 100644 lib/src/main/java/oiccli/client_info/Usage.java diff --git a/lib/src/main/java/com/auth0/jwt/creators/Message.java b/lib/src/main/java/com/auth0/jwt/creators/Message.java index 45d252c..b581670 100644 --- a/lib/src/main/java/com/auth0/jwt/creators/Message.java +++ b/lib/src/main/java/com/auth0/jwt/creators/Message.java @@ -19,10 +19,10 @@ package com.auth0.jwt.creators; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.gson.Gson; - +import com.fasterxml.jackson.databind.ObjectWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -40,8 +40,9 @@ public String toUrlDecoded(String urlEncoded) throws UnsupportedEncodingExceptio return URLDecoder.decode(urlEncoded, "UTF-8"); } - public String toJSON(HashMap hashMap) { - return new Gson().toJson(hashMap); + public String toJSON() throws JsonProcessingException { + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + return ow.writeValueAsString(this); } public HashMap fromJSON(String json) throws IOException { diff --git a/lib/src/main/java/oiccli/FakeResponse.java b/lib/src/main/java/oiccli/FakeResponse.java new file mode 100644 index 0000000..fcd5158 --- /dev/null +++ b/lib/src/main/java/oiccli/FakeResponse.java @@ -0,0 +1,17 @@ +package oiccli; + +import java.util.HashMap; +import java.util.Map; + +public class FakeResponse { + + private Map headers; + private String text; + + public FakeResponse(String header) { + Map headersTemp = new HashMap<>(); + headers.put("contentType", header); + this.headers = headersTemp; + this.text = "TEST_RESPONSE"; + } +} diff --git a/lib/src/main/java/oiccli/HTTP/CookieJar.java b/lib/src/main/java/oiccli/HTTP/CookieJar.java new file mode 100644 index 0000000..f143bed --- /dev/null +++ b/lib/src/main/java/oiccli/HTTP/CookieJar.java @@ -0,0 +1,4 @@ +package oiccli.HTTP; + +public class CookieJar { +} diff --git a/lib/src/main/java/oiccli/HTTP/FileCookieJar.java b/lib/src/main/java/oiccli/HTTP/FileCookieJar.java new file mode 100644 index 0000000..c8ba94f --- /dev/null +++ b/lib/src/main/java/oiccli/HTTP/FileCookieJar.java @@ -0,0 +1,4 @@ +package oiccli.HTTP; + +public class FileCookieJar { +} diff --git a/lib/src/main/java/oiccli/HTTP/Http.java b/lib/src/main/java/oiccli/HTTP/Http.java index f144305..21d52e5 100644 --- a/lib/src/main/java/oiccli/HTTP/Http.java +++ b/lib/src/main/java/oiccli/HTTP/Http.java @@ -2,6 +2,7 @@ import java.util.HashMap; import java.util.Map; +import oiccli.exceptions.ValueError; public class Http { @@ -12,13 +13,13 @@ public class Http { private Object events; private Object reqCallback; - public Http(String caCerts, boolean shouldVerifySSL, KeyJar keyjar, String clientCert) { + public Http(String caCerts, boolean shouldVerifySSL, KeyJar keyjar, String clientCert) throws ValueError { this.caCerts = caCerts; this.requestArgs = new HashMap() {{ put("allowRedirects", false); }}; this.keyJar = keyjar; //or KeyJar(verify_ssl=verify_ssl) - //this.cookiejar = FileCookieJar() + this.cookiejar = FileCookieJar(); if (caCerts != null) { if (!shouldVerifySSL) { throw new ValueError("conflict: ca_certs defined, but verify_ssl is False"); diff --git a/lib/src/main/java/oiccli/Service.java b/lib/src/main/java/oiccli/Service.java index c9406b3..c448621 100644 --- a/lib/src/main/java/oiccli/Service.java +++ b/lib/src/main/java/oiccli/Service.java @@ -3,6 +3,7 @@ import com.auth0.jwt.creators.Message; import com.google.common.base.Strings; import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; import java.net.URI; import java.net.URISyntaxException; import java.text.ParseException; @@ -11,6 +12,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import javax.xml.ws.http.HTTPException; import oiccli.HTTP.Response; import oiccli.client_info.ClientInfo; @@ -67,33 +69,60 @@ public class Service { private List preConstruct; private List postConstruct; private List postParseResponse; + private Map conf; - public Service(String httpLib, KeyJar keyJar, String clientAuthenticationMethod, Map args) { + public Service(String httpLib, KeyJar keyJar, String clientAuthenticationMethod, Map conf, Map args) throws NoSuchFieldException, IllegalAccessException { this.httpLib = httpLib; this.keyJar = keyJar; this.clientAuthenticationMethod = clientAuthenticationMethod; this.events = new ArrayList<>(); this.endpoint = ""; this.defaultRequestArgs = new HashMap<>(); + + if(conf != null) { + this.conf = conf; + List params = Arrays.asList("msgType", "responseCls", "errorMsg", "defaultAuthenticationMethod", + "httpMethod", "bodyType", "responseBodyType"); + for(String param : params) { + if(conf.containsKey(param)) { + this.getClass().getField(param).set(this, conf.get("param")); + } + } + } else { + this.conf = new HashMap<>(); + } + this.preConstruct = new ArrayList<>(); this.postConstruct = new ArrayList<>(); this.postParseResponse = new ArrayList<>(); - this.httpMethod = "GET"; - this.bodyType = "urlencoded"; - this.responseBodyType = "json"; - this.defaultAuthenticationMethod = ""; - this.request = ""; - this.endpoint = ""; - this.endpointName = ""; - this.setUp(); } - public void gatherRequestArgs(ClientInfo clientInfo, Map args) { + public Map gatherRequestArgs(ClientInfo clientInfo, Map args) throws NoSuchFieldException { + Map arArgs = new HashMap<>(args); + Set properties = this.msgType.getCParam().keySet(); + Field field; + for(String property : properties) { + if(!arArgs.containsKey(property)) { + field = clientInfo.getClass().getField(property); + if(field != null) { + arArgs.put(property, field); + } else { + field = this.conf.getRequestArgs().getProp(); + if(field != null) { + arArgs.put(property, field); + } else { + arArgs.put(property, this.defaultRequestArgs.get(property)); + } + } + } + } + + return arArgs; } - public static Map> updateHttpArgs(Map httpArgs, Map> info) { + public static Map updateHttpArgs(Map httpArgs, Map> info) { Map hArgs = info.get("hArgs"); if (hArgs == null) { hArgs = new HashMap<>(); @@ -161,7 +190,7 @@ public Message constructMessage(ClientInfo clientInfo, Map reque List> returnedArgs = this.doPreConstruct(clientInfo, requestArgs, args); - if (!this.msgType.c_param.containsKey("state")) { + if (!this.msgType.getCParam().containsKey("state")) { args.remove("state"); } @@ -295,7 +324,8 @@ public Map doRequestInit(ClientInfo clientInfo, String bodyType, } public String getUrlInfo(String info) throws URISyntaxException { - String query = null, fragment = null; + String query = null; + String fragment = null; if (info.contains("?") || info.contains("#")) { URI uri = new URI(info); query = uri.getQuery(); @@ -395,7 +425,7 @@ public String getValueType(FakeResponse response, String bodyType) throws WrongC } } - public ErrorResponse parseRequestResponse(ErrorResponse response, ClientInfo clientInfo, String responseBodyType, + public static ErrorResponse parseRequestResponse(ErrorResponse response, ClientInfo clientInfo, String responseBodyType, String state, Map args) { int statusCode = response.getStatusCode(); if (successfulCodes.contains(statusCode)) { diff --git a/lib/src/main/java/oiccli/State.java b/lib/src/main/java/oiccli/State.java index 93e008a..06287c1 100644 --- a/lib/src/main/java/oiccli/State.java +++ b/lib/src/main/java/oiccli/State.java @@ -144,7 +144,7 @@ public Map getTokenInfo(String state) throws ExpiredToken { return getTokenInfo(state, 0); } - public Map getResponseArgs(String state, ABCMeta request, int now) throws ExpiredToken { + public Map getResponseArgs(String state, AccessTokenRequest request, int now) throws ExpiredToken { Map info = state.getState(state); Map responseArgs = new HashMap<>(); for (String claim : request.c_param) { diff --git a/lib/src/main/java/oiccli/Util.java b/lib/src/main/java/oiccli/Util.java index 4ef8f42..f6c968e 100644 --- a/lib/src/main/java/oiccli/Util.java +++ b/lib/src/main/java/oiccli/Util.java @@ -1,6 +1,7 @@ package oiccli; import com.auth0.jwt.creators.Message; +import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.base.Strings; import java.io.UnsupportedEncodingException; import java.text.DateFormat; @@ -66,7 +67,7 @@ public static Map getOrPost(String uri, String method, Message c return getOrPost(uri, method, cis, DEFAULT_POST_CONTENT_TYPE, null, args); } - public static Map getOrPost(String uri, String method, Message request, String contentType, String accept, Map args) throws UnsupportedEncodingException, UnsupportedType { + public static Map getOrPost(String uri, String method, Message request, String contentType, String accept, Map args) throws UnsupportedEncodingException, UnsupportedType, JsonProcessingException { Map response = new HashMap<>(); String urlEncoded; if (method.equals("GET") || method.equals("DELETE")) { @@ -81,7 +82,7 @@ public static Map getOrPost(String uri, String method, Message r if (contentType.equals(URL_ENCODED)) { response.put("body", request.toUrlEncoded(request.toString())); } else if (contentType.equals(JSON_ENCODED)) { - response.put("body", request.toJSON(request.toHashMap())); + response.put("body", request.toJSON()); } else { throw new UnsupportedType("Unsupported content type " + contentType); } @@ -212,7 +213,7 @@ public static String verifyHeader(FakeResponse response, String bodyType) throws } else if (bodyType.equals(JSON)) { if (matchTo(JWT_ENCODED, contentType)) { bodyType = JWT; - } else { + } else if(!matchTo(JSON_ENCODED, contentType) || !matchTo(JRD_JSON, contentType)){ throw new WrongContentType(contentType); } } else if (bodyType.equals(JWT)) { diff --git a/lib/src/main/java/oiccli/Utils.java b/lib/src/main/java/oiccli/Utils.java new file mode 100644 index 0000000..7723948 --- /dev/null +++ b/lib/src/main/java/oiccli/Utils.java @@ -0,0 +1,80 @@ +package oiccli; + +import com.auth0.jwt.creators.Message; +import com.google.common.base.Strings; +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Map; +import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingRequiredAttribute; + +public class Utils { + + public static Message requestObjectEncryption(Message message, ClientInfo clientInfo, Map args) throws MissingRequiredAttribute { + String encryptionAlg = (String) args.get("requestObjectEncryptionAlg"); + + if(Strings.isNullOrEmpty(encryptionAlg)) { + List listOfAlgs = clientInfo.getBehavior().get("requestObjectEncryptionAlg"); + if(listOfAlgs != null || !listOfAlgs.isEmpty()) { + encryptionAlg = listOfAlgs.get(0); + } + + if(encryptionAlg == null) { + return message; + } + } + + String encryptionEnc = (String) args.get("requestObjectEncryptionEnc"); + + if(Strings.isNullOrEmpty(encryptionEnc)) { + List listOfAlgs = clientInfo.getBehavior().get("requestObjectEncryptionEnc"); + if(listOfAlgs != null || !listOfAlgs.isEmpty()) { + encryptionEnc = listOfAlgs.get(0); + } + + if(encryptionEnc == null) { + throw new MissingRequiredAttribute("No requestObjectEncryptionEnc specified"); + } + } + + JWE jwe = new JWE(message, encryptionAlg, encryptionEnc); + String keyType = StringUtil.alg2keytype(encryptionAlg); + + String kid = (String) args.get("encKid"); + if(Strings.isNullOrEmpty(kid)) { + kid = ""; + } + + if(!args.containsKey("target")) { + throw new MissingRequiredAttribute("No target specified"); + } + + List keys; + if(!Strings.isNullOrEmpty(kid)) { + keys = clientInfo.getKeyJar().getEncryptKey(keyType, args.get("target"), kid); + jwe.setKid(kid); + } else { + keys = clientInfo.getKeyJar().getEncryptKey(keyType, args.get("target")); + } + + return jwe.encrypt(keys); + } + + public static Tuple constructRequestUri(String localDir, String basePath, Map args) { + File file = new File(localDir); + if(!file.isDirectory()) { + file.mkdirs(); + } + String name = StringUtil.generateRandomString(10) + ".jwt"; + File fileExists = Paths.get(localDir, name).toFile(); + while(fileExists.exists()) { + name = StringUtil.generateRandomString(10); + fileExists = Paths.get(localDir, name).toFile(); + } + + String webName = basePath + name; + return new Tuple(fileExists.toString(), webName); + } +} diff --git a/lib/src/main/java/oiccli/client_auth/BearerHeader.java b/lib/src/main/java/oiccli/client_auth/BearerHeader.java index 9a27c4c..22d4163 100644 --- a/lib/src/main/java/oiccli/client_auth/BearerHeader.java +++ b/lib/src/main/java/oiccli/client_auth/BearerHeader.java @@ -3,11 +3,12 @@ import java.util.HashMap; import java.util.Map; import oiccli.client_info.ClientInfo; +import oiccli.exceptions.MissingRequiredAttribute; public class BearerHeader { public Map> construct(Map cis, ClientInfo clientInfo, Map requestArgs, Map> httpArgs, - Map args) { + Map args) throws MissingRequiredAttribute { String accessToken; if (cis != null) { if (cis.containsKey("accessToken")) { @@ -16,19 +17,15 @@ public Map> construct(Map cis, Clien //cis.c_param["access_token"] = SINGLE_OPTIONAL_STRING } else { accessToken = requestArgs.get("accessToken"); - requestArgs.remove(accessToken); - if (accessToken != null) { - accessToken = args.get("accessToken"); - if (accessToken == null) { - accessToken = clientInfo.getStateDb().getTokenInfo(args).get("accessToken"); - } + if (accessToken == null) { + accessToken = clientInfo.getStateDb().getTokenInfo(args).get("accessToken"); } } } else { accessToken = args.get("accessToken"); if (accessToken == null) { - accessToken = requestArgs.get("accessToken"); + throw new MissingRequiredAttribute("accessToken"); } } diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java index cec0542..c581154 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretBasic.java @@ -23,7 +23,7 @@ public static JWT assertionJwt(String clientId, List keys, List aud return token.toJWT(keys, algorithm); } - public Map> construct(Map cis, ClientInfo cliInfo, Map> httpArgs, + public Map> construct(AccessTokenRequest request, ClientInfo cliInfo, Map> httpArgs, Map args) { if (httpArgs == null) { httpArgs = new HashMap<>(); @@ -37,7 +37,7 @@ public Map> construct(Map cis, Clien if (password == null) { password = httpArgs.get("password").get("password"); if (password == null) { - password = cis.get("clientSecret"); + password = request.getClientSecret(); if (password == null) { password = cliInfo.getClientSecret(); } @@ -51,27 +51,21 @@ public Map> construct(Map cis, Clien String credentials = user + ":" + password; String authz = new String(Base64.encodeBase64(credentials.getBytes())); - Map hMap = httpArgs.get("headers"); + Map hMap = new HashMap<>(); hMap.put("Authorization", "Basic " + authz); httpArgs.put("headers", hMap); - cis.remove("clientSecret"); + request.setClientSecret(null); - if (cis.get("grantType").equals("authorizationCode")) { - if (!cis.containsKey("clientId")) { - cis.put("clientId", cliInfo.getClientId()); + if (request.get("grantType").equals("authorizationCode")) { + if (request.getClientId() != null) { + request.setClientId(cliInfo.getClientId()); } } else { - boolean req; - /* - try: - req = cis.c_param["client_id"][VREQUIRED] - except KeyError: - req = False - */ + boolean req = request.getCParam("clientId").get(VREQUIRED); if (!req) { - cis.remove("clientId"); + request.remove("clientId"); } } diff --git a/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java index dffce3f..bb8dfce 100644 --- a/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java +++ b/lib/src/main/java/oiccli/client_auth/ClientSecretPost.java @@ -1,24 +1,26 @@ package oiccli.client_auth; +import com.google.common.base.Strings; import java.util.Map; +import oiccli.client_info.ClientInfo; public class ClientSecretPost extends ClientSecretBasic { - public Map> construct(Map cis, CliInfo cliInfo, Map> httpArgs, + public Map> construct(AccessTokenRequest request, ClientInfo clientInfo, Map> httpArgs, Map args) { - if (!cis.containsKey("clientSecret")) { + if (Strings.isNullOrEmpty(request.getClientSecret())) { Map clientSecret = httpArgs.get("clientSecret"); if (clientSecret != null) { - cis.put("clientSecret", clientSecret.get("clientSecret")); + request.setClientSecret(clientSecret.get("clientSecret")); httpArgs.remove("clientSecret"); } else { - if (cliInfo.getClientSecret() != null) { - cis.put("clientSecret", cliInfo.getClientSecret()); + if (!Strings.isNullOrEmpty(clientInfo.getClientSecret())) { + request.setClientSecret(clientInfo.getClientSecret()); } } } - cis.put("clientId", cliInfo.getClientId()); + request.setClientId(clientInfo.getClientId()); return httpArgs; } diff --git a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java index 686e0d7..bcf927d 100644 --- a/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java +++ b/lib/src/main/java/oiccli/client_auth/JWSAuthenticationMethod.java @@ -20,6 +20,7 @@ public class JWSAuthenticationMethod extends ClientAuthenticationMethod { put("private_key_jwt", "RS256"); }}; private static final String JWT_BEARER = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"; + private static final String V_Required = 1; public static String chooseAlgorithm(String entity, Map args) throws AuthenticationFailure { String algorithm = args.get("algorithm"); @@ -58,24 +59,24 @@ public Key getKeyByKid(String kid, String algorithm, ClientInfo clientInfo) thro } } - public Map construct(Map cis, ClientInfo clientInfo, Map requestArgs, + public Map construct(AccessTokenRequest request, ClientInfo clientInfo, Map requestArgs, Map httpArgs, Map args) throws AuthenticationFailure, NoMatchingKey { String algorithm = null; List audience = null; if (args.containsKey("clientAssertion")) { - cis.put("clientAssertion", args.get("clientAssertion")); + request.setClientAssertion(args.get("clientAssertion")); if (args.containsKey("clientAssertionType")) { - cis.put("clientAssertionType", args.get("clientAssertionType")); + request.setClientAssertionType(args.get("clientAssertionType")); } else { - cis.put("clientAssertionType", JWT_BEARER); + request.setClientAssertionType(JWT_BEARER); } - } else if (cis.containsKey("clientAssertion")) { - if (!cis.containsKey("clientAssertionType")) { - cis.put("clientAssertionType", JWT_BEARER); + } else if (request.getClientAssertion() != null) { + if (request.getClientAssertionType() == null) { + request.setClientAssertionType(JWT_BEARER); } } else { if (args.get("authenticationEndpoint").equals("token") || args.get("authenticationEndpoint").equals("refresh")) { - algorithm = clientInfo.registrationInfo("tokenEndpointAuthSigningAlg"); + algorithm = clientInfo.registrationInfo().get("tokenEndpointAuthSigningAlg"); audience = clientInfo.getProviderInfo().get("tokenEndpoint"); } else { audience = clientInfo.getProviderInfo().get("issuer"); @@ -102,12 +103,12 @@ public Map construct(Map cis, ClientInfo clientI Map hMap = new HashMap<>(); hMap.put("lifetime", args.get("lifetime")); - cis.put("clientAssertion", BearerBody.assertionJWT(clientInfo.getClientId(), signingKey, audience, algorithm, 600)); - cis.put("clientAssertionType", JWT_BEARER); - cis.remove("clientSecret"); + request.setClientAssertion(BearerBody.assertionJWT(clientInfo.getClientId(), signingKey, audience, algorithm, 600)); + request.setClientAssertionType(JWT_BEARER); + request.setClientSecret(null); - if (cis.get("clientId").get(1)) { - cis.remove("clientId"); + if (request.getCParam.getClientId().get(V_Required) == null) { + request.setClientId(null); } return new HashMap<>(); diff --git a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java index 8ca47f3..34c546f 100644 --- a/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java +++ b/lib/src/main/java/oiccli/client_auth/PrivateKeyJwt.java @@ -21,4 +21,20 @@ public String chooseAlgorithm(Map args) throws AuthenticationFai public Key getSigningKey(String algorithm, ClientInfo clientInfo) { return clientInfo.getKeyJar().getSigningKey(StringUtil.alg2keytype(algorithm), "", algorithm); } + + public static boolean validClientInfo(ClientInfo clientInfo, long when) { + long eta = clientInfo.getClientSecretExpiresAt(); + long now; + if(when != 0) { + now = when; + } else { + now = System.currentTimeMillis(); + } + + if(eta != 0 && eta < now) { + return false; + } + + return true; + } } diff --git a/lib/src/main/java/oiccli/client_info/ClientInfo.java b/lib/src/main/java/oiccli/client_info/ClientInfo.java index a2af899..36070e7 100644 --- a/lib/src/main/java/oiccli/client_info/ClientInfo.java +++ b/lib/src/main/java/oiccli/client_info/ClientInfo.java @@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableMap; import com.sun.org.apache.xml.internal.security.utils.Base64; import java.io.File; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -12,39 +14,51 @@ import oiccli.State; import oiccli.StringUtil; import oiccli.exceptions.ExpiredToken; +import oiccli.exceptions.ValueError; import org.junit.Assert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ClientInfo { + private static final String S256 = "S256"; + private static final String SHA_256 = "SHA-256"; + private static final String SHA_384 = "SHA-384"; + private static final String SHA_512 = "SHA-512"; + private static final String S384 = "S384"; + private static final String S512 = "S512"; + private static final String RS256 = "RS256"; + private static final String HS256 = "HS256"; + private static final String ALG = "alg"; + private static final String ENC = "enc"; + private static final String SIGN = "sign"; private static final Map userInfoMap = - ImmutableMap.of("sign", "userinfoSignedResponseAlg", - "alg", "userinfoEncryptedResponseAlg", - "enc", "userinfoEncryptedResponseEnc"); + ImmutableMap.of(SIGN, "userinfoSignedResponseAlg", + ALG, "userinfoEncryptedResponseAlg", + ENC, "userinfoEncryptedResponseEnc"); private static final Map idTokenMap = - ImmutableMap.of("sign", "idTokenSignedResponseAlg", - "alg", "idTokenEncryptedResponseAlg", - "enc", "idTokenEncryptedResponseEnc"); + ImmutableMap.of(SIGN, "idTokenSignedResponseAlg", + ALG, "idTokenEncryptedResponseAlg", + ENC, "idTokenEncryptedResponseEnc"); private static final Map requestMap = - ImmutableMap.of("sign", "requestObjectSigningAlg", - "alg", "requestObjectEncryptionAlg", - "enc", "requestObjectEncryptionEnc"); + ImmutableMap.of(SIGN, "requestObjectSigningAlg", + ALG, "requestObjectEncryptionAlg", + ENC, "requestObjectEncryptionEnc"); private static final Map> attributeMap = ImmutableMap.of("userinfo", userInfoMap, "idToken", idTokenMap, "request", requestMap); private static final Map defSignAlg = - ImmutableMap.of("idToken", "RS256", - "userInfo", "RS256", - "requestObject", "RS256", - "clientSecretJwt", "HS256", - "privateKeyJwt", "RS256"); + ImmutableMap.of("idToken", RS256, + "userInfo", RS256, + "requestObject", RS256, + "clientSecretJwt", HS256, + "privateKeyJwt", RS256); private KeyJar keyJar; private State stateDb; private List events; private boolean shouldBeStrictOnPreferences; private Map> providerInfo; - private Map registrationResponse; + private Map> registrationResponse; private String registrationExpires; private String registrationAccessToken; private Map> kid; @@ -71,7 +85,7 @@ public ClientInfo(KeyJar keyjar, Map config, List events this.registrationResponse = new HashMap<>(); this.kid = new HashMap() {{ put("sig", new HashMap<>()); - put("enc", new HashMap<>()); + put(ENC, new HashMap<>()); }}; this.config = config; this.baseUrl = ""; @@ -163,10 +177,6 @@ public void importKeys(Map>> keySpec) { } } - public String getCSecret() { - return this.cSecret; - } - public String getIssuer() { return issuer; } @@ -204,7 +214,15 @@ public Map> getKid() { } public void setClientSecret(String cSecret) { - this.cSecret = cSecret; + if(Strings.isNullOrEmpty(cSecret)) { + this.cSecret = ""; + } else { + this.cSecret = cSecret; + if(this.keyJar == null) { + this.keyJar = new KeyJar(); + } + this.keyJar.addSymmetric("", cSecret); + } } public State getState() { @@ -235,22 +253,14 @@ public void setClientId(String clientId) { this.stateDb.setClientId(clientId); } - public void setRegistrationResponse(Map registrationResponse) { + public void setRegistrationResponse(Map> registrationResponse) { this.registrationResponse = registrationResponse; } - public Map getRegistrationResponse() { + public Map> getRegistrationResponse() { return this.registrationResponse; } - public String getRegistrationExpires() { - return registrationExpires; - } - - public String getRegistrationAccessToken() { - return registrationAccessToken; - } - public void setRegistrationAccessToken(String registrationAccessToken) { this.registrationAccessToken = registrationAccessToken; } @@ -263,18 +273,14 @@ public State getStateDb() { return stateDb; } - public void setStateDb(State stateDb) { - this.stateDb = stateDb; - } - //client_id = property(get_client_id, set_client_id) - public void setItem(String key, String value) throws NoSuchFieldException, IllegalAccessException { - this.getClass().getField(key).set(key, value); - } - - public String filenameFromWebname(String webName) { - Assert.assertTrue(webName.startsWith(this.baseUrl)); + public String filenameFromWebname(String webName) throws ValueError { + try { + Assert.assertTrue(webName.startsWith(this.baseUrl)); + } catch (AssertionError e) { + throw new ValueError("Webname doesn't match baseUrl"); + } webName = webName.substring(baseUrl.length()); if (webName.startsWith("/")) { return webName.substring(1); @@ -283,16 +289,16 @@ public String filenameFromWebname(String webName) { } } - public Map signEncAlgs(SignEncAlgs type) { - Map response = new HashMap<>(); - String value; + public Map> signEncAlgs(SignEncAlgs type) { + Map> response = new HashMap<>(); + List value; for (String key : attributeMap.get(type).keySet()) { value = this.registrationResponse.get(attributeMap.get(key)); if (attributeMap.get(key) != null && value != null) { response.put(key, value); } else { - if (key.equals("sign")) { - response.put(key, defSignAlg.get(type)); + if (key.equals(SIGN)) { + response.put(key, Arrays.asList(defSignAlg.get(type))); } } } @@ -305,20 +311,24 @@ public boolean verifyAlgSupport(String algorithm, VerifyAlgSupportUsage usage, V return supported.contains(algorithm); } - public List generateRequestUris(String requestsDir) { - //m = hashlib.sha256() - String issuer = this.providerInfo.get("issuer"); - if (issuer != null) { - m.update(issuer.getBytes()); + public List generateRequestUris(String requestsDir) throws NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance(SHA_256); + List providerInfoList = this.providerInfo.get("issuer"); + if(providerInfoList != null && !providerInfoList.isEmpty()) { + String providerInfo = providerInfoList.get(0); + if(!Strings.isNullOrEmpty(providerInfo)) { + digest.update(providerInfo.getBytes()); + } } else { - m.update(this.issuer); + digest.update(this.issuer.getBytes()); } - m.update(this.baseUrl.getBytes()); - return this.baseUrl + requestsDir + "/" + m.hexDigest(); + digest.update(this.baseUrl.getBytes()); + + return Arrays.asList(this.baseUrl + requestsDir + "/" + digest.digest()); } - public static List addCodeChallenge(ClientInfo clientInfo, String state) { + public static Map addCodeChallenge(ClientInfo clientInfo, String state) throws NoSuchAlgorithmException { Integer cvLength = (Integer) clientInfo.config.get("codeChallenge").get("length"); if (cvLength == null) { cvLength = 64; @@ -329,25 +339,44 @@ public static List addCodeChallenge(ClientInfo clientInfo, String state) String method = (String) clientInfo.config.get("codeChallenge").get("method"); if (method == null) { - method = "S256"; + method = S256; } - /* - try: - _h = CC_METHOD[_method](_cv).hexdigest() - code_challenge = b64e(_h.encode()).decode() - except KeyError: - raise Unsupported( - 'PKCE Transformation method:{}'.format(_method)) - */ + MessageDigest digest= null; + switch (method) { + case S256: + digest = MessageDigest.getInstance(SHA_256); + break; + case S384: + digest = MessageDigest.getInstance(SHA_384); + break; + case S512: + digest = MessageDigest.getInstance(SHA_512); + break; + } + + String codeVerifierHex = bytesToHex(codeVerifier.getBytes()); + + byte[] codeVerifierHexByteArr = digest.digest(codeVerifierHex.getBytes()); + String codeChallenge = Base64.encode(codeVerifierHexByteArr); - clientInfo.getStateDb().addInfo(state, null); + clientInfo.getStateDb().addInfo(state, codeVerifier, method); Map hMap = new HashMap<>(); hMap.put("codeChallenge", codeChallenge); hMap.put("codeChallengeMethod", method); - return Arrays.asList(hMap, codeVerifier); + return hMap; + } + + private static String bytesToHex(byte[] hash) { + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < hash.length; i++) { + String hex = Integer.toHexString(0xff & hash[i]); + if(hex.length() == 1) hexString.append('0'); + hexString.append(hex); + } + return hexString.toString(); } public void setRegistrationExpires(String registrationExpires) { diff --git a/lib/src/main/java/oiccli/client_info/Usage.java b/lib/src/main/java/oiccli/client_info/Usage.java deleted file mode 100644 index b9f329c..0000000 --- a/lib/src/main/java/oiccli/client_info/Usage.java +++ /dev/null @@ -1,5 +0,0 @@ -package oiccli.client_info; - -public enum Usage { - USER_INFO, ID_TOKEN, REQUEST_OBJECT, TOKEN_ENDPOINT_AUTH; -} diff --git a/lib/src/main/java/oiccli/service/Authorization.java b/lib/src/main/java/oiccli/service/Authorization.java index aef6c8a..8fd9db1 100644 --- a/lib/src/main/java/oiccli/service/Authorization.java +++ b/lib/src/main/java/oiccli/service/Authorization.java @@ -1,5 +1,7 @@ package oiccli.service; +import com.auth0.jwt.creators.Message; +import com.google.common.base.Strings; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; @@ -9,6 +11,8 @@ import java.util.Map; import oiccli.AuthorizationResponse; import oiccli.StringUtil; +import oiccli.Tuple; +import oiccli.Utils; import oiccli.client_info.ClientInfo; public class Authorization extends service.Authorization { @@ -103,18 +107,22 @@ public Map oicPostConstruct(ClientInfo clientInfo, Map oicPostConstruct(ClientInfo clientInfo, Map>> oicPreConstruct(ClientInfo clientInfo, Ma requestArgs.put("redirectUris", clientInfo.getRedirectUris()); } - if (clientInfo.getProviderInfo().get("requireRequestUriRegistration")) { + if (!Strings.isNullOrEmpty(clientInfo.getProviderInfo().get("requireRequestUriRegistration").get(0))) { requestArgs.put("requestUris", clientInfo.generateRequestUris(clientInfo.getRequestsDir())); } return Arrays.asList(requestArgs, new HashMap>()); } - public void oicPostParseResponse(Map response, ClientInfo cliInfo) { + public void oicPostParseResponse(Map> response, ClientInfo cliInfo) { cliInfo.setRegistrationResponse(response); if (!cliInfo.getRegistrationResponse().containsKey("tokenEndpointAuthMethod")) { - Map hMap = cliInfo.getRegistrationResponse(); - hMap.put("tokenEndpointAuthMethod", "clientSecretBasic"); + Map> hMap = cliInfo.getRegistrationResponse(); + hMap.put("tokenEndpointAuthMethod", Arrays.asList("clientSecretBasic")); cliInfo.setRegistrationResponse(hMap); } - cliInfo.setClientId(response.get("clientId")); - cliInfo.setClientSecret(response.get("clientSecret")); - cliInfo.setRegistrationExpires(response.get("clientSecretExpiresAt")); - cliInfo.setRegistrationAccessToken(response.get("registrationAccessToken")); + cliInfo.setClientId(response.get("clientId").get(0)); + cliInfo.setClientSecret(response.get("clientSecret").get(0)); + cliInfo.setRegistrationExpires(response.get("clientSecretExpiresAt").get(0)); + cliInfo.setRegistrationAccessToken(response.get("registrationAccessToken").get(0)); } } diff --git a/lib/src/main/java/oiccli/webfinger/JRD.java b/lib/src/main/java/oiccli/webfinger/JRD.java index f7ed17b..ea7388d 100644 --- a/lib/src/main/java/oiccli/webfinger/JRD.java +++ b/lib/src/main/java/oiccli/webfinger/JRD.java @@ -1,16 +1,13 @@ package oiccli.webfinger; +import com.auth0.jwt.creators.Message; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -public class JRD extends Base { +public class JRD extends Message { private static final Map cParam = new HashMap() {{ - put("expires", new HashMap() {{ - put("type", String.class); - put("required", false); - }}); put("subject", new HashMap() {{ put("type", String.class); put("required", false); diff --git a/lib/src/main/java/oiccli/webfinger/URINormalizer.java b/lib/src/main/java/oiccli/webfinger/URINormalizer.java index 4b564aa..1d8cdb6 100644 --- a/lib/src/main/java/oiccli/webfinger/URINormalizer.java +++ b/lib/src/main/java/oiccli/webfinger/URINormalizer.java @@ -23,7 +23,7 @@ public boolean hasScheme(String path) { return true; } - public boolean isAccountSchemeAssumed(String path) { + public static boolean isAccountSchemeAssumed(String path) { String[] arr; if (path.contains("@")) { arr = path.split("@"); diff --git a/lib/src/main/java/oiccli/webfinger/WebFinger.java b/lib/src/main/java/oiccli/webfinger/WebFinger.java index b55cecc..ba497f3 100644 --- a/lib/src/main/java/oiccli/webfinger/WebFinger.java +++ b/lib/src/main/java/oiccli/webfinger/WebFinger.java @@ -1,6 +1,8 @@ package oiccli.webfinger; +import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.base.Strings; +import com.google.gson.Gson; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; @@ -26,6 +28,7 @@ public class WebFinger { private static final String WF_URL = "https://%s/.well-known/webfinger"; final private static Logger logger = LoggerFactory.getLogger(WebFinger.class); private static final String OIC_ISSUER = "http://openid.net/specs/connect/1.0/issuer"; + private static final Gson gson = new Gson(); public WebFinger(String defaultRelt, Object httpd) { this.defaultRelt = defaultRelt; @@ -85,7 +88,7 @@ public static JRD load(Map item) { return new JRD(json.loads(item)); } - public Map> httpArgs(JRD jrd) { + public Map httpArgs(JRD jrd) throws JsonProcessingException { if (jrd == null) { if (this.jrd != null) { jrd = this.jrd; @@ -99,68 +102,19 @@ public Map> httpArgs(JRD jrd) { put("Content-Type", "application/json; charset=UTF-8"); }}; - Map> headersAndBody = new HashMap<>(); + Map headersAndBody = new HashMap<>(); headersAndBody.put("headers", hMap); - headersAndBody.put("body", json.dumps(jrd.export())); + headersAndBody.put("body", jrd.toJSON()); return headersAndBody; } - /* - TODO: I don't see this in Roland's code anymore; might want to remove - public String discoveryQuery(String resource) throws URISyntaxException, WebFingerError { - logger.debug("Looking for OIDC OP for '" + resource + "'"); - String url = this.query(resource, Arrays.asList(OIC_ISSUER)); - HttpResponse response = this.httpd(url, true); - int statusCode = response.getStatusCode(); - Map hMap = new HashMap<>(); - if(statusCode == 200) { - if(this.events != null) { - hMap.put("Response", response.getResponseHeader()); - this.events.add(hMap); - } - - this.jrd = load(response.getResponseHeader()); - if(this.events != null) { - hMap = new HashMap<>(); - hMap.put("JRD Response", this.jrd); - this.events.add(hMap); - } - for(Object link : this.jrd.getcParam().get("links")) { - if(link.getRel().equals(OIC_ISSUER)) { - if(!link.getHRef().startsWith("https://")) { - throw new WebFingerError("Must be a HTTPS href"); - } - return link.getHRef(); - } - } - return null; - } else if(statusCode == 301 || statusCode == 302 || statusCode == 307) { - return this.discoveryQuery(response.getResponseHeader("location")); - } else { - throw new WebFingerError("Status code is: " + statusCode); - } - }*/ - - /*public String response(String subject, String base, Map args) throws NoSuchFieldException, IllegalAccessException { - this.jrd = new JRD(); - this.jrd.setSubject(subject); - Base.link.put("rel", OIC_ISSUER); - Base.link.put("href", base); - this.jrd.setLinks(Arrays.asList(Base.link)); - for(String key : args.keySet()) { - this.jrd.getClass().getField(key).set(key, args.get(key)); - } - return json.dumps(this.jrd.export()); - }*/ - - public static Object linkDeser(Object val, String sFormat) { if (val instanceof Map) { return val; } else if (sFormat.equals("dict") || sFormat.equals("json")) { if (!(val instanceof String)) { - val = json.dumps(val); + val = gson.toJson(val); sFormat = "json"; } } @@ -173,7 +127,7 @@ public static Object messageSer(Object inst, String sFormat, int lev) throws Mes if (sFormat.equals("urlencoded") || sFormat.equals("json")) { if (inst instanceof Map) { if (sFormat.equals("json")) { - res = json.dumps(inst); + res = gson.toJson(inst); } else { res = Base64.encodeBase64URLSafe() } From 64cb79267bffc7cfffb5c4d4a7a6fc92dd723c53 Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Tue, 30 Jan 2018 16:58:47 -0300 Subject: [PATCH 09/10] fix timezone issues on exp claim tests --- .../jwt/creators/AccessJwtCreatorTest.java | 13 ++--- .../jwt/creators/ExtendedJwtCreatorTest.java | 14 ++--- .../auth0/jwt/creators/FbJwtCreatorTest.java | 13 ++--- .../jwt/creators/GoogleJwtCreatorTest.java | 56 +++++++++---------- .../jwt/creators/RiscJwtCreatorTest.java | 13 ++--- .../jwt/creators/ScopedJwtCreatorTest.java | 15 ++--- 6 files changed, 52 insertions(+), 72 deletions(-) diff --git a/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java index b9e7087..2f2b769 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/AccessJwtCreatorTest.java @@ -317,14 +317,11 @@ public void testAccessJwtCreatorNonStandardClaimDateValue() throws Exception { @Test public void testAccessJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = AccessJwtCreator.build() @@ -332,7 +329,7 @@ public void testAccessJwtCreatorExpTimeHasPassed() throws Exception { .withSubject("subject") .withAudience("audience") .withNonStandardClaim("nonStandardClaim", new Date()) - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .sign(algorithm); Verification verification = AccessJWT.require(algorithm); diff --git a/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java index 445f0b0..87a583f 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/ExtendedJwtCreatorTest.java @@ -40,6 +40,7 @@ import org.junit.rules.ExpectedException; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; import java.util.Map; @@ -441,14 +442,11 @@ public void testExtendedJwtCreatorNonStandardClaimDateValue() throws Exception { @Test public void testExtendedJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = ExtendedJwtCreator.build() @@ -458,7 +456,7 @@ public void testExtendedJwtCreatorExpTimeHasPassed() throws Exception { .withIssuer("issuer") .withSubject("subject") .withAudience("audience") - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .withName(NAME) .withNonStandardClaim("nonStandardClaim", new Date()) diff --git a/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java index b6cb74e..b6b1121 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/FbJwtCreatorTest.java @@ -322,18 +322,15 @@ public void testFbJwtCreatorNonStandardClaimDateValue() throws Exception { } @Test public void testFbJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = FbJwtCreator.build() - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .withUserId(USER_ID) .withAppId(APP_ID) diff --git a/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java index ceba3d9..b0ec885 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/GoogleJwtCreatorTest.java @@ -19,10 +19,7 @@ package com.auth0.jwt.creators; -import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; -import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; import com.auth0.jwt.algorithms.Algorithm; -import com.auth0.jwt.creators.GoogleJwtCreator; import com.auth0.jwt.exceptions.InvalidClaimException; import com.auth0.jwt.exceptions.TokenExpiredException; import com.auth0.jwt.impl.PublicClaims; @@ -31,15 +28,18 @@ import com.auth0.jwt.interfaces.GoogleVerification; import com.auth0.jwt.jwts.GoogleJWT; import com.auth0.jwt.jwts.JWT; -import static java.util.Arrays.asList; -import static org.junit.Assert.assertTrue; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import java.util.Calendar; +import java.util.Date; +import java.util.Map; -import java.text.SimpleDateFormat; -import java.util.*; +import static com.auth0.jwt.TimeUtil.generateRandomExpDateInFuture; +import static com.auth0.jwt.TimeUtil.generateRandomIatDateInPast; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertTrue; public class GoogleJwtCreatorTest { @@ -133,7 +133,7 @@ public void testGoogleJwtCreatorWhenCertainRequiredClaimIsntProvided() throws Ex GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); } @@ -157,7 +157,7 @@ public void testGoogleJwtCreatorNoneAlgorithmNotAllowed() throws Exception { GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); } @@ -180,7 +180,7 @@ public void testGoogleJwtCreatorNoneAlgorithmNotSpecifiedButStillNotAllowed() th GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); } @@ -201,7 +201,7 @@ public void testGoogleJwtCreatorNoneAlgorithmAllowed() throws Exception { GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); Map claims = jwt.getClaims(); verifyClaims(claims, exp); @@ -251,7 +251,7 @@ public void testGoogleJwtCreatorInvalidIssuer() throws Exception { GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); } @@ -363,7 +363,7 @@ public void testGoogleJwtCreatorNonStandardClaimString() throws Exception { .sign(algorithm); GoogleVerification verification = GoogleJWT.require(algorithm); JWT verifier = verification.createVerifierForGoogle(PICTURE, EMAIL, asList("issuer"), asList("audience"), - NAME, 1, 1).build(); + NAME, 1, 1).build(); DecodedJWT jwt = verifier.decode(token); Map claims = jwt.getClaims(); verifyClaims(claims, exp); @@ -481,14 +481,11 @@ public void testGoogleJwtCreatorNonStandardClaimDate() throws Exception { @Test public void testGoogleJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = GoogleJwtCreator.build() @@ -497,7 +494,7 @@ public void testGoogleJwtCreatorExpTimeHasPassed() throws Exception { .withIssuer("issuer") .withSubject("subject") .withAudience("audience") - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .withName(NAME) .sign(algorithm); @@ -509,14 +506,11 @@ public void testGoogleJwtCreatorExpTimeHasPassed() throws Exception { @Test public void testGoogleJwtCreatorTokenCantBeUsedBefore() throws Exception { - thrown.expect(InvalidClaimException.class); - thrown.expectMessage("The Token can't be used before Mon Oct 29 00:00:00 PDT 2018."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2018, Calendar.OCTOBER, 29); - String myDate = "2018/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date iatDate = new Date(expLong); + thrown.expect(InvalidClaimException.class); + thrown.expectMessage(String.format("The Token can't be used before %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = GoogleJwtCreator.build() @@ -526,7 +520,7 @@ public void testGoogleJwtCreatorTokenCantBeUsedBefore() throws Exception { .withSubject("subject") .withAudience("audience") .withExp(exp) - .withIat(iatDate) + .withIat(calendar.getTime()) .withName(NAME) .sign(algorithm); GoogleVerification verification = GoogleJWT.require(algorithm); @@ -536,14 +530,14 @@ public void testGoogleJwtCreatorTokenCantBeUsedBefore() throws Exception { } @Test - public void testCreateVerifierForExtended() throws Exception{ + public void testCreateVerifierForExtended() throws Exception { thrown.expect(UnsupportedOperationException.class); thrown.expectMessage("you shouldn't be calling this method"); GoogleVerification verification = GoogleJWT.require(Algorithm.HMAC256("secret")); verification.createVerifierForExtended(null, null, null, null, null, 1L, 1L, 1L); } - protected static void verifyClaims(Map claims, Date exp) { + protected static void verifyClaims(Map claims, Date exp) { assertTrue(claims.get(PICTURE).asString().equals(PICTURE)); assertTrue(claims.get(EMAIL).asString().equals(EMAIL)); assertTrue(claims.get(PublicClaims.ISSUER).asList(String.class).get(0).equals("issuer")); diff --git a/lib/src/test/java/com/auth0/jwt/creators/RiscJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/RiscJwtCreatorTest.java index 31a03ef..2248ae0 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/RiscJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/RiscJwtCreatorTest.java @@ -378,14 +378,11 @@ public void testRiscJwtCreatorNonStandardClaimDateValue() throws Exception { @Test public void testRiscJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = RiscJwtCreator.build() @@ -394,7 +391,7 @@ public void testRiscJwtCreatorExpTimeHasPassed() throws Exception { .withSubject("subject") .withAudience("audience") .withNonStandardClaim("nonStandardClaim", new Date()) - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .sign(algorithm); Verification verification = RiscJWT.require(algorithm); diff --git a/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java b/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java index 5ebb397..5878ed0 100644 --- a/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java +++ b/lib/src/test/java/com/auth0/jwt/creators/ScopedJwtCreatorTest.java @@ -370,14 +370,11 @@ public void testScopedJwtCreatorNonStandardClaimDateValue() throws Exception { @Test public void testScopedJwtCreatorExpTimeHasPassed() throws Exception { - thrown.expect(TokenExpiredException.class); - thrown.expectMessage("The Token has expired on Wed Oct 29 00:00:00 PDT 2014."); + Calendar calendar = Calendar.getInstance(); + calendar.set(2014, Calendar.OCTOBER, 29); - String myDate = "2014/10/29"; - SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); - Date date = sdf.parse(myDate); - long expLong = date.getTime(); - Date expDate = new Date(expLong); + thrown.expect(TokenExpiredException.class); + thrown.expectMessage(String.format("The Token has expired on %s", calendar.getTime())); Algorithm algorithm = Algorithm.HMAC256("secret"); String token = ScopedJwtCreator.build() @@ -386,14 +383,14 @@ public void testScopedJwtCreatorExpTimeHasPassed() throws Exception { .withSubject("subject") .withAudience("audience") .withNonStandardClaim("nonStandardClaim", new Date()) - .withExp(expDate) + .withExp(calendar.getTime()) .withIat(iat) .sign(algorithm); Verification verification = ScopedJWT.require(algorithm); JWT verifier = verification.createVerifierForScoped("scope", asList("issuer"), asList("audience"), 1, 1).build(); DecodedJWT jwt = verifier.decode(token); Map claims = jwt.getClaims(); - verifyClaims(claims, expDate); + verifyClaims(claims, calendar.getTime()); } private static void verifyClaims(Map claims, Date exp) { From 491b6db179caa17e4742c56b1ec43b35bf7d305c Mon Sep 17 00:00:00 2001 From: Luciano Balmaceda Date: Tue, 30 Jan 2018 16:58:54 -0300 Subject: [PATCH 10/10] fix javadoc syntax --- lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java | 2 +- lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java index 91eb070..f3f946c 100644 --- a/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java +++ b/lib/src/main/java/com/auth0/jwt/jwts/ImplicitJWT.java @@ -34,9 +34,9 @@ public class ImplicitJWT extends JWT.BaseVerification implements Verification{ /** * Create Verification object for verification purposes - * @issuer scope * @param issuer * @param audience + * @param iatLeeway * @return */ public Verification createVerifierForImplicit(List issuer, diff --git a/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java b/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java index 0354502..6fbb790 100644 --- a/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java +++ b/lib/src/main/java/com/auth0/jwt/jwts/ScopedJWT.java @@ -34,9 +34,11 @@ public class ScopedJWT extends JWT.BaseVerification implements Verification{ /** * Create Verification object for verification purposes - * @issuer scope + * @param scope * @param issuer * @param audience + * @param expLeeway + * @param iatLeeway * @return */ public Verification createVerifierForScoped(String scope, List issuer,