From 94895269ec2668acf2eed2a19a75719b86eddcc7 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 25 Aug 2016 16:00:40 +0200 Subject: [PATCH 001/104] Travis: Generate release in Zip and Tar.gz format --- .travis.yml | 2 +- build.gradle | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2b68406..d3ad1c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: java jdk: - oraclejdk8 script: -- ./gradlew releaseZip +- ./gradlew release after_success: - bash <(curl -s https://codecov.io/bash) deploy: diff --git a/build.gradle b/build.gradle index b92989d..399e9dc 100644 --- a/build.gradle +++ b/build.gradle @@ -166,6 +166,10 @@ task releaseTarGz(type: Tar, dependsOn: ['clean', 'jar', 'bowerInstall', 'npmIns archiveName = "identio-server.tar.gz" } +task release(dependsOn: ['releaseTarGz', 'releaseZip']) { + description 'Build release in zip and tar.gz format' +} + task wrapper(type: Wrapper) { gradleVersion = '2.14' } From 753252d7634e0d6ad6a8b25c89014310d279f0af Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Fri, 26 Aug 2016 13:27:51 +0200 Subject: [PATCH 002/104] Allow configuration of the public FQDN through a run parameter --- sample-config/identio-config.yml | 3 --- .../server/model/GlobalConfiguration.java | 9 --------- .../configuration/ConfigurationService.java | 16 +++++++++++++--- .../server/service/saml/MetadataService.java | 8 ++++---- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/sample-config/identio-config.yml b/sample-config/identio-config.yml index 3601624..964dbb5 100644 --- a/sample-config/identio-config.yml +++ b/sample-config/identio-config.yml @@ -1,6 +1,3 @@ -globalConfiguration: - publicFqdn: http://idp.identio.net:10080 - authPolicyConfiguration: authLevels: - &low diff --git a/src/main/java/net/identio/server/model/GlobalConfiguration.java b/src/main/java/net/identio/server/model/GlobalConfiguration.java index 633e2d1..89c0c17 100644 --- a/src/main/java/net/identio/server/model/GlobalConfiguration.java +++ b/src/main/java/net/identio/server/model/GlobalConfiguration.java @@ -21,7 +21,6 @@ License, or (at your option) any later version. public class GlobalConfiguration { - private String publicUrl; private int port; private boolean secure; private String keystorePath; @@ -29,14 +28,6 @@ public class GlobalConfiguration { private String workDirectory; private String staticResourcesPath; - public String getPublicFqdn() { - return publicUrl; - } - - public void setPublicFqdn(String publicFqdn) { - this.publicUrl = publicFqdn; - } - public int getPort() { return port; } diff --git a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java index d70d9ee..ebfbca8 100644 --- a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java +++ b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java @@ -42,12 +42,18 @@ public class ConfigurationService { private IdentioConfiguration configuration; private String configFile; - + private String publicFqdn; + @Autowired - public ConfigurationService(@Value("${identio.config}") String configFile) throws InitializationException { + public ConfigurationService(@Value("${identio.config}") String configFile, @Value("${identio.public.fqdn}") String publicFqdn) throws InitializationException { + if (publicFqdn == null) { + throw new InitializationException("No public FQDN specified"); + } + this.configFile = configFile; - + this.publicFqdn = publicFqdn; + LOG.debug("Loading configuration file: {}", configFile); try (FileInputStream is = new FileInputStream(configFile)) { @@ -67,6 +73,10 @@ public ConfigurationService(@Value("${identio.config}") String configFile) throw } } + public String getPublicFqdn() { + return publicFqdn; + } + public IdentioConfiguration getConfiguration() { return configuration; } diff --git a/src/main/java/net/identio/server/service/saml/MetadataService.java b/src/main/java/net/identio/server/service/saml/MetadataService.java index d1ed919..2b6f578 100644 --- a/src/main/java/net/identio/server/service/saml/MetadataService.java +++ b/src/main/java/net/identio/server/service/saml/MetadataService.java @@ -98,14 +98,14 @@ private void initIdpMetadata() throws TechnicalException, InitializationExceptio // Determine idp endpoint configuration ArrayList idpEndpoints = new ArrayList<>(); - String idpPostUrl = config.getGlobalConfiguration().getPublicFqdn() + "/SAML2/SSO/POST"; - String idpRedirectUrl = config.getGlobalConfiguration().getPublicFqdn() + "/SAML2/SSO/Redirect"; + String idpPostUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/POST"; + String idpRedirectUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/Redirect"; idpEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_REDIRECT, idpRedirectUrl, true)); idpEndpoints.add(new Endpoint(2, SamlConstants.BINDING_HTTP_POST, idpPostUrl, false)); // Determine sp endpoint configuration ArrayList spEndpoints = new ArrayList<>(); - String spPostUrl = config.getGlobalConfiguration().getPublicFqdn() + "/SAML2/ACS/POST"; + String spPostUrl = configurationService.getPublicFqdn() + "/SAML2/ACS/POST"; spEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_POST, spPostUrl, true)); // Extract certificate from provided P12 @@ -144,7 +144,7 @@ private void initIdpMetadata() throws TechnicalException, InitializationExceptio .setWantAssertionsSigned(false).setSigningCertificates(certs); idpMetadata = MetadataBuilder.getInstance() - .setEntityID(config.getGlobalConfiguration().getPublicFqdn() + "/SAML2") + .setEntityID(configurationService.getPublicFqdn() + "/SAML2") .setOrganizationName(config.getSamlIdpConfiguration().getOrganizationName()) .setOrganizationDisplayName(config.getSamlIdpConfiguration().getOrganizationDisplayName()) .setOrganizationURL(config.getSamlIdpConfiguration().getOrganizationUrl()) From ca3b0e1b44a84458ab26213828e85576d9137e42 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Sun, 11 Dec 2016 16:11:11 +0100 Subject: [PATCH 003/104] Initialize objects by default in the ConfigurationService --- .../net/identio/server/model/IdentioConfiguration.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/identio/server/model/IdentioConfiguration.java b/src/main/java/net/identio/server/model/IdentioConfiguration.java index 4fa8fda..86e0e23 100644 --- a/src/main/java/net/identio/server/model/IdentioConfiguration.java +++ b/src/main/java/net/identio/server/model/IdentioConfiguration.java @@ -21,11 +21,11 @@ License, or (at your option) any later version. public class IdentioConfiguration { - private GlobalConfiguration globalConfiguration; - private SamlIdpConfiguration samlIdpConfiguration; - private SessionConfiguration sessionConfiguration; - private AuthPolicyConfiguration authPolicyConfiguration; - private AuthMethodConfiguration authMethodConfiguration; + private GlobalConfiguration globalConfiguration = new GlobalConfiguration(); + private SamlIdpConfiguration samlIdpConfiguration = new SamlIdpConfiguration(); + private SessionConfiguration sessionConfiguration = new SessionConfiguration(); + private AuthPolicyConfiguration authPolicyConfiguration = new AuthPolicyConfiguration(); + private AuthMethodConfiguration authMethodConfiguration = new AuthMethodConfiguration(); public GlobalConfiguration getGlobalConfiguration() { return globalConfiguration; From 4f16b3214b9d7af6b2a0f827127443ce8d01aa00 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Sun, 11 Dec 2016 16:11:39 +0100 Subject: [PATCH 004/104] Throw an error if no SAML response endpoints are found --- .../java/net/identio/server/service/saml/SamlService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index 5849431..4021b1e 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -157,6 +157,11 @@ public AuthRequestValidationResult validateAuthentRequest(InboundRequest request String requestId = ar.getId(); Endpoint destinationEndpoint = findResponseEndpoint(ar); + if (destinationEndpoint == null) { + LOG.error("No suitable response endpoint found"); + return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_UNKNOWN_ENDPOINT); + } + result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) .setForceAuthentication(forceAuthn).setRequestType(RequestType.SAML) .setRelayState(request.getRelayState()).setResponseUrl(destinationEndpoint.getLocation()); From 7d3a6de4925cd7fa3ec1a22700e8d92bc9c61409 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Sun, 11 Dec 2016 22:50:16 +0100 Subject: [PATCH 005/104] Adapted model, controllers and validation service in order to consume oath requests --- .../model/AuthorizationConfiguration.java | 35 +++++++ .../server/model/IdentioConfiguration.java | 18 ++++ .../identio/server/model/InboundRequest.java | 95 +------------------ .../net/identio/server/model/OAuthClient.java | 71 ++++++++++++++ .../server/model/OAuthInboundRequest.java | 60 ++++++++++++ .../server/model/OAuthResponseType.java | 15 +++ .../model/OAuthServerConfiguration.java | 34 +++++++ .../server/model/SamlInboundRequest.java | 89 +++++++++++++++++ .../java/net/identio/server/model/Scope.java | 43 +++++++++ .../java/net/identio/server/model/State.java | 2 +- .../server/mvc/oauth/OAuthController.java | 82 ++++++++++++++++ .../mvc/saml/RequestConsumerController.java | 4 +- .../server/service/oauth/OauthService.java | 30 +++++- .../server/service/saml/SamlService.java | 6 +- .../service/validation/ValidationService.java | 11 ++- 15 files changed, 488 insertions(+), 107 deletions(-) create mode 100644 src/main/java/net/identio/server/model/AuthorizationConfiguration.java create mode 100644 src/main/java/net/identio/server/model/OAuthClient.java create mode 100644 src/main/java/net/identio/server/model/OAuthInboundRequest.java create mode 100644 src/main/java/net/identio/server/model/OAuthResponseType.java create mode 100644 src/main/java/net/identio/server/model/OAuthServerConfiguration.java create mode 100644 src/main/java/net/identio/server/model/SamlInboundRequest.java create mode 100644 src/main/java/net/identio/server/model/Scope.java create mode 100644 src/main/java/net/identio/server/mvc/oauth/OAuthController.java diff --git a/src/main/java/net/identio/server/model/AuthorizationConfiguration.java b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java new file mode 100644 index 0000000..c35b3ce --- /dev/null +++ b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java @@ -0,0 +1,35 @@ +/* + This file is part of Ident.io. + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.model; + +import java.util.List; + +public class AuthorizationConfiguration { + + private List scopes; + + public List getScopes() { + return scopes; + } + + public void setScopes(List scopes) { + this.scopes = scopes; + } +} diff --git a/src/main/java/net/identio/server/model/IdentioConfiguration.java b/src/main/java/net/identio/server/model/IdentioConfiguration.java index 86e0e23..b7b2ed6 100644 --- a/src/main/java/net/identio/server/model/IdentioConfiguration.java +++ b/src/main/java/net/identio/server/model/IdentioConfiguration.java @@ -26,6 +26,8 @@ public class IdentioConfiguration { private SessionConfiguration sessionConfiguration = new SessionConfiguration(); private AuthPolicyConfiguration authPolicyConfiguration = new AuthPolicyConfiguration(); private AuthMethodConfiguration authMethodConfiguration = new AuthMethodConfiguration(); + private OAuthServerConfiguration oAuthServerConfiguration = new OAuthServerConfiguration(); + private AuthorizationConfiguration authorizationConfiguration = new AuthorizationConfiguration(); public GlobalConfiguration getGlobalConfiguration() { return globalConfiguration; @@ -66,4 +68,20 @@ public AuthMethodConfiguration getAuthMethodConfiguration() { public void setAuthMethodConfiguration(AuthMethodConfiguration authMethodConfiguration) { this.authMethodConfiguration = authMethodConfiguration; } + + public OAuthServerConfiguration getoAuthServerConfiguration() { + return oAuthServerConfiguration; + } + + public void setoAuthServerConfiguration(OAuthServerConfiguration oAuthServerConfiguration) { + this.oAuthServerConfiguration = oAuthServerConfiguration; + } + + public AuthorizationConfiguration getAuthorizationConfiguration() { + return authorizationConfiguration; + } + + public void setAuthorizationConfiguration(AuthorizationConfiguration authorizationConfiguration) { + this.authorizationConfiguration = authorizationConfiguration; + } } diff --git a/src/main/java/net/identio/server/model/InboundRequest.java b/src/main/java/net/identio/server/model/InboundRequest.java index ac64214..9206f7a 100644 --- a/src/main/java/net/identio/server/model/InboundRequest.java +++ b/src/main/java/net/identio/server/model/InboundRequest.java @@ -1,98 +1,5 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ package net.identio.server.model; -public class InboundRequest { - - private RequestType type = RequestType.SAML; - private String binding; - private String serializedRequest; - private String signatureValue; - private String signedInfo; - private String signatureAlgorithm; - private String relayState; - - public InboundRequest(String binding, String serializedRequest, String signatureValue, String signedInfo, - String signatureAlgorithm, String relayState) { - this.binding = binding; - this.serializedRequest = serializedRequest; - this.signatureValue = signatureValue; - this.signedInfo = signedInfo; - this.signatureAlgorithm = signatureAlgorithm; - this.relayState = relayState; - } - - public RequestType getType() { - return type; - } - - public void setType(RequestType type) { - this.type = type; - } - - public String getBinding() { - return binding; - } - - public void setBinding(String binding) { - this.binding = binding; - } - - public String getSerializedRequest() { - return serializedRequest; - } - - public void setSerializedRequest(String serializedRequest) { - this.serializedRequest = serializedRequest; - } - - public String getSignatureValue() { - return signatureValue; - } - - public void setSignatureValue(String signatureValue) { - this.signatureValue = signatureValue; - } - - public String getSignedInfo() { - return signedInfo; - } - - public void setSignedInfo(String signedInfo) { - this.signedInfo = signedInfo; - } - - public String getSignatureAlgorithm() { - return signatureAlgorithm; - } - - public void setSignatureAlgorithm(String signatureAlgorithm) { - this.signatureAlgorithm = signatureAlgorithm; - } - - public String getRelayState() { - return relayState; - } - - public void setRelayState(String relayState) { - this.relayState = relayState; - } +public interface InboundRequest { } diff --git a/src/main/java/net/identio/server/model/OAuthClient.java b/src/main/java/net/identio/server/model/OAuthClient.java new file mode 100644 index 0000000..12b6aa4 --- /dev/null +++ b/src/main/java/net/identio/server/model/OAuthClient.java @@ -0,0 +1,71 @@ +/* + This file is part of Ident.io. + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.model; + +import java.util.List; + +public class OAuthClient { + + private String name; + private String clientId; + private String clientSecret; + private List allowedScopes; + private List responseUri; + + public String getName() { + return name; + } + + public void setToto(String name) { + this.name = name; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public List getAllowedScopes() { + return allowedScopes; + } + + public void setAllowedScopes(List allowedScopes) { + this.allowedScopes = allowedScopes; + } + + public List getResponseUri() { + return responseUri; + } + + public void setResponseUri(List responseUri) { + this.responseUri = responseUri; + } +} diff --git a/src/main/java/net/identio/server/model/OAuthInboundRequest.java b/src/main/java/net/identio/server/model/OAuthInboundRequest.java new file mode 100644 index 0000000..e6b36ce --- /dev/null +++ b/src/main/java/net/identio/server/model/OAuthInboundRequest.java @@ -0,0 +1,60 @@ +package net.identio.server.model; + +public class OAuthInboundRequest implements InboundRequest { + + private String clientId; + private String responseType; + private String redirectUri; + private String[] scopes; + private String state; + + public OAuthInboundRequest(String clientId, String responseType, String redirectUri, String[] scopes, + String state) { + + this.clientId = clientId; + this.responseType = responseType; + this.redirectUri = redirectUri; + this.scopes = scopes; + this.state = state; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public String[] getScopes() { + return scopes; + } + + public void setScopes(String[] scopes) { + this.scopes = scopes; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } +} diff --git a/src/main/java/net/identio/server/model/OAuthResponseType.java b/src/main/java/net/identio/server/model/OAuthResponseType.java new file mode 100644 index 0000000..81e4ed0 --- /dev/null +++ b/src/main/java/net/identio/server/model/OAuthResponseType.java @@ -0,0 +1,15 @@ +package net.identio.server.model; + +public enum OAuthResponseType { + CODE("code"), TOKEN("token"); + + private String name; + + OAuthResponseType(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } +} diff --git a/src/main/java/net/identio/server/model/OAuthServerConfiguration.java b/src/main/java/net/identio/server/model/OAuthServerConfiguration.java new file mode 100644 index 0000000..cd63068 --- /dev/null +++ b/src/main/java/net/identio/server/model/OAuthServerConfiguration.java @@ -0,0 +1,34 @@ +/* + This file is part of Ident.io. + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.model; + +public class OAuthServerConfiguration { + + private String clientFile; + + public String getClientFile() { + return clientFile; + } + + public void setClientFile(String clientFile) { + this.clientFile = clientFile; + } + +} diff --git a/src/main/java/net/identio/server/model/SamlInboundRequest.java b/src/main/java/net/identio/server/model/SamlInboundRequest.java new file mode 100644 index 0000000..3c71a56 --- /dev/null +++ b/src/main/java/net/identio/server/model/SamlInboundRequest.java @@ -0,0 +1,89 @@ +/* + This file is part of Ident.io. + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.model; + +public class SamlInboundRequest implements InboundRequest { + + private String binding; + private String serializedRequest; + private String signatureValue; + private String signedInfo; + private String signatureAlgorithm; + private String relayState; + + public SamlInboundRequest(String binding, String serializedRequest, String signatureValue, String signedInfo, + String signatureAlgorithm, String relayState) { + this.binding = binding; + this.serializedRequest = serializedRequest; + this.signatureValue = signatureValue; + this.signedInfo = signedInfo; + this.signatureAlgorithm = signatureAlgorithm; + this.relayState = relayState; + } + + public String getBinding() { + return binding; + } + + public void setBinding(String binding) { + this.binding = binding; + } + + public String getSerializedRequest() { + return serializedRequest; + } + + public void setSerializedRequest(String serializedRequest) { + this.serializedRequest = serializedRequest; + } + + public String getSignatureValue() { + return signatureValue; + } + + public void setSignatureValue(String signatureValue) { + this.signatureValue = signatureValue; + } + + public String getSignedInfo() { + return signedInfo; + } + + public void setSignedInfo(String signedInfo) { + this.signedInfo = signedInfo; + } + + public String getSignatureAlgorithm() { + return signatureAlgorithm; + } + + public void setSignatureAlgorithm(String signatureAlgorithm) { + this.signatureAlgorithm = signatureAlgorithm; + } + + public String getRelayState() { + return relayState; + } + + public void setRelayState(String relayState) { + this.relayState = relayState; + } + +} diff --git a/src/main/java/net/identio/server/model/Scope.java b/src/main/java/net/identio/server/model/Scope.java new file mode 100644 index 0000000..8dd418d --- /dev/null +++ b/src/main/java/net/identio/server/model/Scope.java @@ -0,0 +1,43 @@ +/* + This file is part of Ident.io. + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.model; + +public class Scope { + + private String name; + private AuthLevel authLevel; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public AuthLevel getAuthLevel() { + return authLevel; + } + + public void setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + } + +} diff --git a/src/main/java/net/identio/server/model/State.java b/src/main/java/net/identio/server/model/State.java index 04c44ec..bcc7939 100644 --- a/src/main/java/net/identio/server/model/State.java +++ b/src/main/java/net/identio/server/model/State.java @@ -20,5 +20,5 @@ License, or (at your option) any later version. package net.identio.server.model; public enum State { - AUTH, STEP_UP_AUTHENTICATION, RESPONSE + AUTH, STEP_UP_AUTHENTICATION, RESPONSE, CONSENT } diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java new file mode 100644 index 0000000..b22f8fa --- /dev/null +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -0,0 +1,82 @@ +/* + This file is part of Ident.io + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.mvc.oauth; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.CookieValue; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import net.identio.server.exceptions.ServerException; +import net.identio.server.exceptions.ValidationException; +import net.identio.server.model.OAuthInboundRequest; +import net.identio.server.model.ValidationResult; +import net.identio.server.mvc.common.PreAuthController; +import net.identio.server.service.validation.ValidationService; + +@Controller +public class OAuthController { + + private static final Logger LOG = LoggerFactory.getLogger(OAuthController.class); + + @Autowired + private ValidationService validationService; + @Autowired + private PreAuthController preAuthController; + + @RequestMapping(value = "/oauth/authorize", method = RequestMethod.GET) + public String authorizeRequest(@RequestParam("response_type") String responseType, + @RequestParam("client_id") String clientId, + @RequestParam(value = "redirect_uri", required = false) String redirectUri, + @RequestParam(value = "scope", required = false) String scopes, + @RequestParam(value = "state", required = false) String state, + @CookieValue(required = false) String identioSession, + HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ValidationException, ServerException { + + LOG.info("Received OAuth authorization request from ClientId: {}", clientId); + LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); + + // Scopes are separated by a space + String[] scopesArray = scopes.split(" "); + + OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesArray, state); + + ValidationResult result = validationService.validateAuthentRequest(request, identioSession); + + switch (result.getState()) { + case RESPONSE: + return "redirect:" + result.getResponseData(); + + case CONSENT: + return "redirect:/#/consent/"; + + default: + return preAuthController.checkTransparentAuthentication(httpRequest, httpResponse, result); + } + } + +} diff --git a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java index 500b772..5907071 100644 --- a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java @@ -42,7 +42,7 @@ License, or (at your option) any later version. import net.identio.server.exceptions.ServerException; import net.identio.server.exceptions.UnknownAuthLevelException; import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.InboundRequest; +import net.identio.server.model.SamlInboundRequest; import net.identio.server.model.State; import net.identio.server.model.ValidationResult; import net.identio.server.mvc.common.PreAuthController; @@ -170,7 +170,7 @@ private String processRequest(HttpServletRequest httpRequest, HttpServletRespons LOG.debug("Processing SAML authentication request."); - InboundRequest samlRequest = new InboundRequest(binding, request, signatureValue, signedInfo, sigAlg, + SamlInboundRequest samlRequest = new SamlInboundRequest(binding, request, signatureValue, signedInfo, sigAlg, relayState); // The request is forwarded to the validation service diff --git a/src/main/java/net/identio/server/service/oauth/OauthService.java b/src/main/java/net/identio/server/service/oauth/OauthService.java index dd3db3a..ce2253a 100644 --- a/src/main/java/net/identio/server/service/oauth/OauthService.java +++ b/src/main/java/net/identio/server/service/oauth/OauthService.java @@ -19,19 +19,43 @@ License, or (at your option) any later version. */ package net.identio.server.service.oauth; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.InboundRequest; +import net.identio.server.model.OAuthInboundRequest; +import net.identio.server.model.OAuthResponseType; +import net.identio.server.model.RequestType; +import net.identio.server.service.configuration.ConfigurationService; @Service @Scope("singleton") public class OauthService { - public AuthRequestValidationResult validateAuthentRequest(InboundRequest request) { + private ConfigurationService configurationService; - throw new UnsupportedOperationException(); + public OauthService(@Autowired ConfigurationService configurationService) { + this.configurationService = configurationService; + } + + public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) { + + AuthRequestValidationResult result = new AuthRequestValidationResult(); + + // Validate response type + try { + OAuthResponseType.valueOf(request.getResponseType()); + } catch (IllegalArgumentException e) { + // TODO: handle error + } + // Verify clientId + + // Verify scope + + // Verify redirectUri + + return result; } } diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index 4021b1e..50a640c 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -61,9 +61,9 @@ License, or (at your option) any later version. import net.identio.server.model.AuthSession; import net.identio.server.model.ErrorStatus; import net.identio.server.model.IdentioConfiguration; -import net.identio.server.model.InboundRequest; import net.identio.server.model.RequestType; import net.identio.server.model.SamlAuthRequestGenerationResult; +import net.identio.server.model.SamlInboundRequest; import net.identio.server.model.UserSession; import net.identio.server.service.authpolicy.AuthPolicyService; import net.identio.server.service.configuration.ConfigurationService; @@ -132,7 +132,7 @@ private void initErrorMapping() { errorMapping.put(ErrorStatus.AUTHENT_REQUEST_NOT_SIGNED, SamlConstants.STATUS_REQUEST_DENIED); } - public AuthRequestValidationResult validateAuthentRequest(InboundRequest request) { + public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest request) { LOG.debug("Starting SAML Authentication Request validation..."); @@ -243,7 +243,7 @@ public AuthRequestValidationResult validateAuthentRequest(InboundRequest request } - private boolean validateRedirectRequest(Validator validator, InboundRequest request, + private boolean validateRedirectRequest(Validator validator, SamlInboundRequest request, AuthRequestValidationResult result) { LOG.debug("Validate query parameters of HTTP-Redirect Binding"); diff --git a/src/main/java/net/identio/server/service/validation/ValidationService.java b/src/main/java/net/identio/server/service/validation/ValidationService.java index a05cf23..3bc8188 100644 --- a/src/main/java/net/identio/server/service/validation/ValidationService.java +++ b/src/main/java/net/identio/server/service/validation/ValidationService.java @@ -44,9 +44,11 @@ License, or (at your option) any later version. import net.identio.server.model.AuthenticationResultStatus; import net.identio.server.model.ErrorStatus; import net.identio.server.model.InboundRequest; +import net.identio.server.model.OAuthInboundRequest; import net.identio.server.model.RequestType; import net.identio.server.model.SamlAuthMethod; import net.identio.server.model.SamlAuthRequestGenerationResult; +import net.identio.server.model.SamlInboundRequest; import net.identio.server.model.State; import net.identio.server.model.TransactionData; import net.identio.server.model.UserSession; @@ -100,10 +102,11 @@ public ValidationResult validateAuthentRequest(InboundRequest request, String se // Validate the request AuthRequestValidationResult arValidationResult = null; - if (request.getType().equals(RequestType.SAML)) { - arValidationResult = samlService.validateAuthentRequest(request); - } else { - arValidationResult = oauthService.validateAuthentRequest(request); + if (request instanceof SamlInboundRequest) { + arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest)request); + } + if (request instanceof OAuthInboundRequest) { + arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest)request); } validationResult.setArValidationResult(arValidationResult); From 5f333de853dd787887d4907c63bfc7a2467942ce Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Mon, 12 Dec 2016 18:00:58 +0100 Subject: [PATCH 006/104] Further adaptations --- .../net/identio/server/model/ErrorStatus.java | 1 + .../net/identio/server/model/OAuthClient.java | 11 +++++- .../server/model/OAuthInboundRequest.java | 32 ++++++++------- .../server/mvc/oauth/OAuthController.java | 5 ++- .../service/oauth/OAuthClientRepository.java | 10 +++++ .../server/service/oauth/OauthService.java | 39 ++++++++++++++----- .../exceptions/ClientNotFoundException.java | 14 +++++++ 7 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java create mode 100644 src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java diff --git a/src/main/java/net/identio/server/model/ErrorStatus.java b/src/main/java/net/identio/server/model/ErrorStatus.java index e4b7875..9622959 100644 --- a/src/main/java/net/identio/server/model/ErrorStatus.java +++ b/src/main/java/net/identio/server/model/ErrorStatus.java @@ -20,5 +20,6 @@ License, or (at your option) any later version. package net.identio.server.model; public enum ErrorStatus { + OAUTH_RESPONSE_TYPE_NOT_SUPPORTED, OAUTH_CLIENT_NOT_FOUND, OAUTH_UNAUTHORIZED_CLIENT, AUTH_USER_ID_MISMATCH, AUTH_SAML_WRONG_AUDIENCE, AUTH_SAML_NO_RECIPIENT, AUTH_SAML_NO_DESTINATION, AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION, AUTH_SAML_CONDITIONS_NOT_MET, AUTH_SAML_INVALID_RESPONSE, AUTH_SAML_REJECTED_BY_PROXY, AUTH_SAML_NO_ASSERTION_IN_RESPONSE, AUTH_SAML_INVALID_INRESPONSETO, AUTH_USER_NOT_UNIQUE, AUTH_INVALID_CREDENTIALS, AUTH_TECHNICAL_ERROR, BUILD_AUTHENT_REQUEST_FAILED, AUTH_LEVEL_UNKNOWN, AUTH_NO_CREDENTIALS, AUTH_METHOD_UNKNOWN, AUTH_METHOD_NOT_ALLOWED, AUTHENT_REQUEST_ISSUER_UNKNOWN, AUTHENT_REQUEST_ISSUER_EMPTY, AUTHENT_REQUEST_NO_DESTINATION, AUTHENT_REQUEST_UNKNOWN_ENDPOINT, AUTHENT_REQUEST_INVALID_ENCODING, AUTHENT_REQUEST_NOT_SIGNED, AUTHENT_REQUEST_SIGNATURE_INVALID } diff --git a/src/main/java/net/identio/server/model/OAuthClient.java b/src/main/java/net/identio/server/model/OAuthClient.java index 12b6aa4..3a8ea49 100644 --- a/src/main/java/net/identio/server/model/OAuthClient.java +++ b/src/main/java/net/identio/server/model/OAuthClient.java @@ -28,7 +28,8 @@ public class OAuthClient { private String clientSecret; private List allowedScopes; private List responseUri; - + private List allowedGrants; + public String getName() { return name; } @@ -68,4 +69,12 @@ public List getResponseUri() { public void setResponseUri(List responseUri) { this.responseUri = responseUri; } + + public List getAllowedGrants() { + return allowedGrants; + } + + public void setAllowedGrants(List allowedGrants) { + this.allowedGrants = allowedGrants; + } } diff --git a/src/main/java/net/identio/server/model/OAuthInboundRequest.java b/src/main/java/net/identio/server/model/OAuthInboundRequest.java index e6b36ce..7448065 100644 --- a/src/main/java/net/identio/server/model/OAuthInboundRequest.java +++ b/src/main/java/net/identio/server/model/OAuthInboundRequest.java @@ -1,16 +1,18 @@ package net.identio.server.model; +import java.util.List; + public class OAuthInboundRequest implements InboundRequest { private String clientId; private String responseType; private String redirectUri; - private String[] scopes; + private List scopes; private String state; - - public OAuthInboundRequest(String clientId, String responseType, String redirectUri, String[] scopes, + + public OAuthInboundRequest(String clientId, String responseType, String redirectUri, List scopes, String state) { - + this.clientId = clientId; this.responseType = responseType; this.redirectUri = redirectUri; @@ -21,39 +23,39 @@ public OAuthInboundRequest(String clientId, String responseType, String redirect public String getClientId() { return clientId; } - + public void setClientId(String clientId) { this.clientId = clientId; } - + public String getResponseType() { return responseType; } - + public void setResponseType(String responseType) { this.responseType = responseType; } - + public String getRedirectUri() { return redirectUri; } - + public void setRedirectUri(String redirectUri) { this.redirectUri = redirectUri; } - - public String[] getScopes() { + + public List getScopes() { return scopes; } - - public void setScopes(String[] scopes) { + + public void setScopes(List scopes) { this.scopes = scopes; } - + public String getState() { return state; } - + public void setState(String state) { this.state = state; } diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index b22f8fa..73a0efa 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -19,6 +19,9 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.oauth; +import java.util.Arrays; +import java.util.List; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -61,7 +64,7 @@ public String authorizeRequest(@RequestParam("response_type") String responseTyp LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); // Scopes are separated by a space - String[] scopesArray = scopes.split(" "); + List scopesArray = Arrays.asList(scopes.split(" ")); OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesArray, state); diff --git a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java new file mode 100644 index 0000000..8d55028 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java @@ -0,0 +1,10 @@ +package net.identio.server.service.oauth; + +import net.identio.server.model.OAuthClient; +import net.identio.server.service.oauth.exceptions.ClientNotFoundException; + +public interface OAuthClientRepository { + + OAuthClient getOAuthClientbyId(String cliendId) throws ClientNotFoundException; + +} diff --git a/src/main/java/net/identio/server/service/oauth/OauthService.java b/src/main/java/net/identio/server/service/oauth/OauthService.java index ce2253a..b544037 100644 --- a/src/main/java/net/identio/server/service/oauth/OauthService.java +++ b/src/main/java/net/identio/server/service/oauth/OauthService.java @@ -24,10 +24,12 @@ License, or (at your option) any later version. import org.springframework.stereotype.Service; import net.identio.server.model.AuthRequestValidationResult; +import net.identio.server.model.ErrorStatus; +import net.identio.server.model.OAuthClient; import net.identio.server.model.OAuthInboundRequest; import net.identio.server.model.OAuthResponseType; -import net.identio.server.model.RequestType; import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.oauth.exceptions.ClientNotFoundException; @Service @Scope("singleton") @@ -35,26 +37,45 @@ public class OauthService { private ConfigurationService configurationService; - public OauthService(@Autowired ConfigurationService configurationService) { + private OAuthClientRepository clientRepository; + + public OauthService(@Autowired ConfigurationService configurationService, + @Autowired OAuthClientRepository clientRepository) { this.configurationService = configurationService; + this.clientRepository = clientRepository; } public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) { AuthRequestValidationResult result = new AuthRequestValidationResult(); - // Validate response type + // Fetch client + OAuthClient client; + try { - OAuthResponseType.valueOf(request.getResponseType()); - } catch (IllegalArgumentException e) { - // TODO: handle error + client = clientRepository.getOAuthClientbyId(request.getClientId()); + } catch (ClientNotFoundException e) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_CLIENT_NOT_FOUND); + + } + + // Validate response type + if (!request.getResponseType().equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains("implicit")) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_RESPONSE_TYPE_NOT_SUPPORTED); } - // Verify clientId - // Verify scope + + // Validate requested scopes + if (!client.getAllowedScopes().containsAll(request.getScopes())) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); + } // Verify redirectUri - + if (!client.getResponseUri().contains(request.getRedirectUri())) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); + } + + return result; } diff --git a/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java b/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java new file mode 100644 index 0000000..9fbedb2 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java @@ -0,0 +1,14 @@ +package net.identio.server.service.oauth.exceptions; + +public class ClientNotFoundException extends Exception { + + private static final long serialVersionUID = -3334461077718669313L; + + public ClientNotFoundException(String s) { + super(s); + } + + public ClientNotFoundException(String s, Throwable e) { + super(s, e); + } +} From b2314bf15819c4d158e7875572fe2185942af549 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Fri, 16 Dec 2016 15:43:14 +0100 Subject: [PATCH 007/104] Implemented OAuth client repository on filesystem --- .../net/identio/server/model/ErrorStatus.java | 2 +- .../net/identio/server/model/OAuthClient.java | 2 +- .../server/service/oauth/OauthService.java | 60 +++++++++++------ .../InvalidRedirectUriException.java | 14 ++++ .../FileOAuthClientRepository.java | 66 +++++++++++++++++++ .../oauth/infrastructure/OAuthClientFile.java | 18 +++++ .../service/oauth/model/OAuthGrants.java | 15 +++++ .../oauth}/model/OAuthResponseType.java | 2 +- .../service/validation/ValidationService.java | 32 +++++---- 9 files changed, 174 insertions(+), 37 deletions(-) create mode 100644 src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java create mode 100644 src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java create mode 100644 src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java create mode 100644 src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java rename src/main/java/net/identio/server/{ => service/oauth}/model/OAuthResponseType.java (80%) diff --git a/src/main/java/net/identio/server/model/ErrorStatus.java b/src/main/java/net/identio/server/model/ErrorStatus.java index 9622959..674a9ad 100644 --- a/src/main/java/net/identio/server/model/ErrorStatus.java +++ b/src/main/java/net/identio/server/model/ErrorStatus.java @@ -20,6 +20,6 @@ License, or (at your option) any later version. package net.identio.server.model; public enum ErrorStatus { - OAUTH_RESPONSE_TYPE_NOT_SUPPORTED, OAUTH_CLIENT_NOT_FOUND, OAUTH_UNAUTHORIZED_CLIENT, + OAUTH_RESPONSE_TYPE_NOT_SUPPORTED, OAUTH_CLIENT_NOT_FOUND, OAUTH_UNAUTHORIZED_CLIENT, OAUTH_INVALID_SCOPE, AUTH_USER_ID_MISMATCH, AUTH_SAML_WRONG_AUDIENCE, AUTH_SAML_NO_RECIPIENT, AUTH_SAML_NO_DESTINATION, AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION, AUTH_SAML_CONDITIONS_NOT_MET, AUTH_SAML_INVALID_RESPONSE, AUTH_SAML_REJECTED_BY_PROXY, AUTH_SAML_NO_ASSERTION_IN_RESPONSE, AUTH_SAML_INVALID_INRESPONSETO, AUTH_USER_NOT_UNIQUE, AUTH_INVALID_CREDENTIALS, AUTH_TECHNICAL_ERROR, BUILD_AUTHENT_REQUEST_FAILED, AUTH_LEVEL_UNKNOWN, AUTH_NO_CREDENTIALS, AUTH_METHOD_UNKNOWN, AUTH_METHOD_NOT_ALLOWED, AUTHENT_REQUEST_ISSUER_UNKNOWN, AUTHENT_REQUEST_ISSUER_EMPTY, AUTHENT_REQUEST_NO_DESTINATION, AUTHENT_REQUEST_UNKNOWN_ENDPOINT, AUTHENT_REQUEST_INVALID_ENCODING, AUTHENT_REQUEST_NOT_SIGNED, AUTHENT_REQUEST_SIGNATURE_INVALID } diff --git a/src/main/java/net/identio/server/model/OAuthClient.java b/src/main/java/net/identio/server/model/OAuthClient.java index 3a8ea49..feaf47c 100644 --- a/src/main/java/net/identio/server/model/OAuthClient.java +++ b/src/main/java/net/identio/server/model/OAuthClient.java @@ -34,7 +34,7 @@ public String getName() { return name; } - public void setToto(String name) { + public void setName(String name) { this.name = name; } diff --git a/src/main/java/net/identio/server/service/oauth/OauthService.java b/src/main/java/net/identio/server/service/oauth/OauthService.java index b544037..841795f 100644 --- a/src/main/java/net/identio/server/service/oauth/OauthService.java +++ b/src/main/java/net/identio/server/service/oauth/OauthService.java @@ -19,6 +19,8 @@ License, or (at your option) any later version. */ package net.identio.server.service.oauth; +import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; @@ -27,56 +29,74 @@ License, or (at your option) any later version. import net.identio.server.model.ErrorStatus; import net.identio.server.model.OAuthClient; import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.model.OAuthResponseType; import net.identio.server.service.configuration.ConfigurationService; import net.identio.server.service.oauth.exceptions.ClientNotFoundException; +import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; +import net.identio.server.service.oauth.model.OAuthGrants; +import net.identio.server.service.oauth.model.OAuthResponseType; @Service @Scope("singleton") public class OauthService { - private ConfigurationService configurationService; - private OAuthClientRepository clientRepository; - public OauthService(@Autowired ConfigurationService configurationService, - @Autowired OAuthClientRepository clientRepository) { - this.configurationService = configurationService; + @Autowired + public OauthService(OAuthClientRepository clientRepository) { this.clientRepository = clientRepository; } - public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) { + public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) + throws ClientNotFoundException, InvalidRedirectUriException { AuthRequestValidationResult result = new AuthRequestValidationResult(); // Fetch client OAuthClient client; - try { - client = clientRepository.getOAuthClientbyId(request.getClientId()); - } catch (ClientNotFoundException e) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_CLIENT_NOT_FOUND); + client = clientRepository.getOAuthClientbyId(request.getClientId()); + // Verify redirectUri + if (!client.getResponseUri().contains(request.getRedirectUri())) { + throw new InvalidRedirectUriException("Unknown redirectUri" + request.getRedirectUri()); } - // Validate response type - if (!request.getResponseType().equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains("implicit")) { + // Validate response type value + if (!checkValidResponseTypes(request.getResponseType())) { return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_RESPONSE_TYPE_NOT_SUPPORTED); } - + // Validate scope value + if (!checkValidScopes(request.getScopes())) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_INVALID_SCOPE); + } - // Validate requested scopes - if (!client.getAllowedScopes().containsAll(request.getScopes())) { + // Validate requested response type + if (!request.getResponseType().equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains(OAuthGrants.IMPLICIT) + || !request.getResponseType().equals(OAuthResponseType.CODE) + && client.getAllowedGrants().contains(OAuthGrants.AUTHORIZATION_CODE)) { return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); } - // Verify redirectUri - if (!client.getResponseUri().contains(request.getRedirectUri())) { + + // Validate requested scopes + if (!client.getAllowedScopes().containsAll(request.getScopes())) { return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); } - - + return result; } + private boolean checkValidResponseTypes(String responseType) { + + // Only valid response types are "token" and "code" + return responseType.equals(OAuthResponseType.CODE) || responseType.equals(OAuthResponseType.CODE); + } + + private boolean checkValidScopes(List scopes) { + + // TODO: to be implemented + + return true; + } + } diff --git a/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java b/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java new file mode 100644 index 0000000..ad7704b --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java @@ -0,0 +1,14 @@ +package net.identio.server.service.oauth.exceptions; + +public class InvalidRedirectUriException extends Exception { + + private static final long serialVersionUID = -3334461077718669313L; + + public InvalidRedirectUriException(String s) { + super(s); + } + + public InvalidRedirectUriException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java new file mode 100644 index 0000000..0886a74 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -0,0 +1,66 @@ +package net.identio.server.service.oauth.infrastructure; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; + +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.OAuthClient; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.oauth.OAuthClientRepository; +import net.identio.server.service.oauth.exceptions.ClientNotFoundException; + +@Service +public class FileOAuthClientRepository implements OAuthClientRepository { + + private static final Logger LOG = LoggerFactory.getLogger(FileOAuthClientRepository.class); + + private HashMap clients; + + @Autowired + public FileOAuthClientRepository(ConfigurationService configurationService) throws InitializationException { + + LOG.info("Initializing File OAUth Client Repository"); + + clients = new HashMap<>(); + + String clientFilePath = configurationService.getConfiguration().getoAuthServerConfiguration().getClientFile(); + + try (FileInputStream is = new FileInputStream(clientFilePath)) { + + Yaml yaml = new Yaml(new CustomClassLoaderConstructor(OAuthClientFile.class, + Thread.currentThread().getContextClassLoader())); + + OAuthClientFile clientFile = (OAuthClientFile) yaml.load(is); + + for (OAuthClient client : clientFile.getOauthClients()) { + clients.put(client.getClientId(), client); + } + + } catch (FileNotFoundException ex) { + throw new InitializationException("OAUth Client Repository file not found", ex); + } catch (IOException ex) { + throw new InitializationException("Impossible to parse OAUth Client Repository file", ex); + } + + LOG.info("* File OAUth Client Repository initialized"); + + } + + @Override + public OAuthClient getOAuthClientbyId(String cliendId) throws ClientNotFoundException { + + if (!clients.containsKey(cliendId)) { throw new ClientNotFoundException("Unknown clientId"); } + + return clients.get(cliendId); + } + +} diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java new file mode 100644 index 0000000..67eaac1 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java @@ -0,0 +1,18 @@ +package net.identio.server.service.oauth.infrastructure; + +import java.util.List; + +import net.identio.server.model.OAuthClient; + +public class OAuthClientFile { + + private List oauthClients; + + public List getOauthClients() { + return oauthClients; + } + + public void setOauthClients(List oauthClients) { + this.oauthClients = oauthClients; + } +} diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java new file mode 100644 index 0000000..28220fe --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java @@ -0,0 +1,15 @@ +package net.identio.server.service.oauth.model; + +public enum OAuthGrants { + IMPLICIT("implicit"), AUTHORIZATION_CODE("authorization_code"); + + private String name; + + OAuthGrants(String name) { + this.name = name; + } + + public String toString() { + return this.name; + } +} diff --git a/src/main/java/net/identio/server/model/OAuthResponseType.java b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java similarity index 80% rename from src/main/java/net/identio/server/model/OAuthResponseType.java rename to src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java index 81e4ed0..de29bac 100644 --- a/src/main/java/net/identio/server/model/OAuthResponseType.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java @@ -1,4 +1,4 @@ -package net.identio.server.model; +package net.identio.server.service.oauth.model; public enum OAuthResponseType { CODE("code"), TOKEN("token"); diff --git a/src/main/java/net/identio/server/service/validation/ValidationService.java b/src/main/java/net/identio/server/service/validation/ValidationService.java index 3bc8188..ac5cf7f 100644 --- a/src/main/java/net/identio/server/service/validation/ValidationService.java +++ b/src/main/java/net/identio/server/service/validation/ValidationService.java @@ -57,6 +57,8 @@ License, or (at your option) any later version. import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; import net.identio.server.service.authpolicy.AuthPolicyService; import net.identio.server.service.oauth.OauthService; +import net.identio.server.service.oauth.exceptions.ClientNotFoundException; +import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; import net.identio.server.service.saml.SamlService; import net.identio.server.service.transaction.TransactionService; import net.identio.server.service.usersession.UserSessionService; @@ -91,13 +93,7 @@ public class ValidationService { public ValidationResult validateAuthentRequest(InboundRequest request, String sessionId) throws ValidationException { - TransactionData transactionData = transactionService.createTransaction(); - UserSession userSession = userSessionService.getUserSession(sessionId); - transactionData.setUserSession(userSession); - ValidationResult validationResult = new ValidationResult(); - validationResult.setTransactionId(transactionData.getTransactionId()); - validationResult.setSessionId(userSession.getId()); // Validate the request AuthRequestValidationResult arValidationResult = null; @@ -106,19 +102,30 @@ public ValidationResult validateAuthentRequest(InboundRequest request, String se arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest)request); } if (request instanceof OAuthInboundRequest) { - arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest)request); + try { + arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest)request); + } catch (ClientNotFoundException | InvalidRedirectUriException e) { + throw new ValidationException("An error occured when processing the request", e); + } } - + validationResult.setArValidationResult(arValidationResult); if (!arValidationResult.isSuccess()) { validationResult.setState(State.RESPONSE); - validationResult.setResponseData(generateFatalErrorResponse(arValidationResult, transactionData)); - + validationResult.setResponseData(generateFatalErrorResponse(arValidationResult)); + return validationResult; } + TransactionData transactionData = transactionService.createTransaction(); + UserSession userSession = userSessionService.getUserSession(sessionId); + transactionData.setUserSession(userSession); + + validationResult.setTransactionId(transactionData.getTransactionId()); + validationResult.setSessionId(userSession.getId()); + // Determine target auth levels and auth methods ArrayList targetAuthLevels = authPolicyService.determineTargetAuthLevel(arValidationResult); HashSet targetAuthMethods = authPolicyService.determineTargetAuthMethods(targetAuthLevels); @@ -355,8 +362,7 @@ private String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestV } } - private String generateFatalErrorResponse(AuthRequestValidationResult arValidationResult, - TransactionData transactionData) throws ValidationException { + private String generateFatalErrorResponse(AuthRequestValidationResult arValidationResult) throws ValidationException { if (arValidationResult.getRequestType() == RequestType.SAML) { @@ -366,8 +372,6 @@ private String generateFatalErrorResponse(AuthRequestValidationResult arValidati String message = "An error occured when generating response"; LOG.error(message); throw new ValidationException(message, e); - } finally { - transactionService.removeTransactionData(transactionData); } } else { throw new UnsupportedOperationException(); From eff4636c13513844a77be69b70b4781eeb19e494 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Sun, 25 Dec 2016 21:40:07 +0100 Subject: [PATCH 008/104] Deleted a buggy check that could directly redirect the user to the error page. This check is not necessary as ui-router won't route to the authController if no transactionId is present --- ui/app/scripts/controllers/authController.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index 98b6455..e539f13 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -35,12 +35,6 @@ // Request the list of authentication methods function init() { - if ($stateParams.transactionId) { - $state.go('error', { - errorCode : 'AUTH_NO_TRANSACTION' - }); - } - vm.submitInProgress = false; vm.methodChoiceEnabled = true; vm.password = null; From 51a7473573b32d74844daa12d01f5f38bcfe9bd4 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Fri, 30 Dec 2016 12:23:41 +0100 Subject: [PATCH 009/104] Implemented implicit oauth flow --- build.gradle | 1 + .../server/boot/BootCustomizationBean.java | 4 +- .../model/AuthRequestValidationResult.java | 39 ++- .../model/AuthorizationConfiguration.java | 6 +- .../{Scope.java => AuthorizationScope.java} | 11 +- .../server/model/GlobalConfiguration.java | 38 ++- .../{RequestType.java => ProtocolType.java} | 2 +- .../server/model/SamlIdpConfiguration.java | 18 -- .../server/model/api/AuthSubmitResponse.java | 21 +- .../server/mvc/common/AuthentController.java | 6 +- .../server/mvc/oauth/OAuthController.java | 9 +- .../authorization/AuthorizationService.java | 68 ++++++ .../exceptions/NoScopeProvidedException.java | 14 ++ .../exceptions/UnknownScopeException.java | 14 ++ .../service/authpolicy/AuthPolicyService.java | 2 +- .../configuration/ConfigurationService.java | 30 +-- .../server/service/oauth/OAuthService.java | 231 ++++++++++++++++++ .../server/service/oauth/OauthService.java | 102 -------- .../FileOAuthClientRepository.java | 2 +- .../oauth/infrastructure/OAuthClientFile.java | 11 +- .../service/oauth/model/OAuthGrants.java | 13 +- .../oauth/model/OAuthResponseType.java | 14 +- .../server/service/saml/MetadataService.java | 4 +- .../server/service/saml/SamlService.java | 10 +- .../service/validation/ValidationService.java | 29 +-- ui/app/index.html | 1 + ui/app/scripts/controllers/authController.js | 14 +- ui/app/scripts/directives/oauth-responder.js | 20 ++ ui/app/scripts/directives/saml-responder.js | 2 +- ui/app/views/auth.html | 2 + 30 files changed, 509 insertions(+), 229 deletions(-) rename src/main/java/net/identio/server/model/{Scope.java => AuthorizationScope.java} (83%) rename src/main/java/net/identio/server/model/{RequestType.java => ProtocolType.java} (96%) create mode 100644 src/main/java/net/identio/server/service/authorization/AuthorizationService.java create mode 100644 src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java create mode 100644 src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java create mode 100644 src/main/java/net/identio/server/service/oauth/OAuthService.java delete mode 100644 src/main/java/net/identio/server/service/oauth/OauthService.java create mode 100644 ui/app/scripts/directives/oauth-responder.js diff --git a/build.gradle b/build.gradle index 399e9dc..e4f6c02 100644 --- a/build.gradle +++ b/build.gradle @@ -51,6 +51,7 @@ dependencies { compile('com.github.identio:identio-saml:1.0.2') compile('com.google.guava:guava:19.0') compile('com.github.detiber:jradius-client:-SNAPSHOT') + compile('com.auth0:java-jwt:3.0.2') providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:${springBootVersion}") providedRuntime('ch.qos.logback:logback-core:1.1.7') providedRuntime('ch.qos.logback:logback-classic:1.1.7') diff --git a/src/main/java/net/identio/server/boot/BootCustomizationBean.java b/src/main/java/net/identio/server/boot/BootCustomizationBean.java index 2e1dfcc..98ad823 100644 --- a/src/main/java/net/identio/server/boot/BootCustomizationBean.java +++ b/src/main/java/net/identio/server/boot/BootCustomizationBean.java @@ -78,9 +78,9 @@ public void customize(Connector connector) { connector.setSecure(true); connector.setScheme("https"); connector.setAttribute("keystoreFile", "file:///" - + configurationService.getConfiguration().getGlobalConfiguration().getKeystorePath()); + + configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePath()); connector.setAttribute("keystorePass", - configurationService.getConfiguration().getGlobalConfiguration().getKeystorePassword()); + configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePassword()); connector.setAttribute("keystoreType", "PKCS12"); connector.setAttribute("keyAlias", "1"); connector.setAttribute("sslProtocol", "TLSv1.2"); diff --git a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java b/src/main/java/net/identio/server/model/AuthRequestValidationResult.java index 2bd42cb..0523839 100644 --- a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java +++ b/src/main/java/net/identio/server/model/AuthRequestValidationResult.java @@ -19,21 +19,23 @@ License, or (at your option) any later version. */ package net.identio.server.model; -import java.util.ArrayList; +import java.util.List; public class AuthRequestValidationResult { private boolean success; private ErrorStatus errorStatus; private String requestId; - private RequestType requestType; + private ProtocolType protocolType; private String sourceApplicationName; private boolean forceAuthentication; private String authLevelComparison; - private ArrayList requestedAuthLevels; + private List requestedAuthLevels; private String relayState; private String responseUrl; - + private List requestedScopes; + private String responseType; + public boolean isSuccess() { return success; } @@ -61,12 +63,12 @@ public AuthRequestValidationResult setRequestId(String requestId) { return this; } - public RequestType getRequestType() { - return requestType; + public ProtocolType getProtocolType() { + return protocolType; } - public AuthRequestValidationResult setRequestType(RequestType requestType) { - this.requestType = requestType; + public AuthRequestValidationResult setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; return this; } @@ -97,11 +99,11 @@ public AuthRequestValidationResult setAuthLevelComparison(String authLevelCompar return this; } - public ArrayList getRequestedAuthLevels() { + public List getRequestedAuthLevels() { return requestedAuthLevels; } - public AuthRequestValidationResult setRequestedAuthLevels(ArrayList requestedAuthLevels) { + public AuthRequestValidationResult setRequestedAuthLevels(List requestedAuthLevels) { this.requestedAuthLevels = requestedAuthLevels; return this; } @@ -123,4 +125,21 @@ public AuthRequestValidationResult setResponseUrl(String responseUrl) { this.responseUrl = responseUrl; return this; } + + public List getRequestedScopes() { + return requestedScopes; + } + + public AuthRequestValidationResult setRequestedScopes(List requestedScopes) { + this.requestedScopes = requestedScopes; + return this; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } } diff --git a/src/main/java/net/identio/server/model/AuthorizationConfiguration.java b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java index c35b3ce..93d8294 100644 --- a/src/main/java/net/identio/server/model/AuthorizationConfiguration.java +++ b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java @@ -23,13 +23,13 @@ License, or (at your option) any later version. public class AuthorizationConfiguration { - private List scopes; + private List scopes; - public List getScopes() { + public List getScopes() { return scopes; } - public void setScopes(List scopes) { + public void setScopes(List scopes) { this.scopes = scopes; } } diff --git a/src/main/java/net/identio/server/model/Scope.java b/src/main/java/net/identio/server/model/AuthorizationScope.java similarity index 83% rename from src/main/java/net/identio/server/model/Scope.java rename to src/main/java/net/identio/server/model/AuthorizationScope.java index 8dd418d..e626f6a 100644 --- a/src/main/java/net/identio/server/model/Scope.java +++ b/src/main/java/net/identio/server/model/AuthorizationScope.java @@ -19,10 +19,11 @@ License, or (at your option) any later version. */ package net.identio.server.model; -public class Scope { +public class AuthorizationScope { private String name; private AuthLevel authLevel; + private int expirationTime; public String getName() { return name; @@ -40,4 +41,12 @@ public void setAuthLevel(AuthLevel authLevel) { this.authLevel = authLevel; } + public int getExpirationTime() { + return expirationTime; + } + + public void setExpirationTime(int expirationTime) { + this.expirationTime = expirationTime; + } + } diff --git a/src/main/java/net/identio/server/model/GlobalConfiguration.java b/src/main/java/net/identio/server/model/GlobalConfiguration.java index 89c0c17..82579da 100644 --- a/src/main/java/net/identio/server/model/GlobalConfiguration.java +++ b/src/main/java/net/identio/server/model/GlobalConfiguration.java @@ -23,8 +23,10 @@ public class GlobalConfiguration { private int port; private boolean secure; - private String keystorePath; - private String keystorePassword; + private String sslKeystorePath; + private String sslKeystorePassword; + private String signatureKeystorePath; + private String signatureKeystorePassword; private String workDirectory; private String staticResourcesPath; @@ -44,20 +46,36 @@ public void setSecure(boolean secure) { this.secure = secure; } - public String getKeystorePath() { - return keystorePath; + public String getSslKeystorePath() { + return sslKeystorePath; } - public void setKeystorePath(String keystorePath) { - this.keystorePath = keystorePath; + public void setSslKeystorePath(String sslKeystorePath) { + this.sslKeystorePath = sslKeystorePath; } - public String getKeystorePassword() { - return keystorePassword; + public String getSslKeystorePassword() { + return sslKeystorePassword; } - public void setKeystorePassword(String keystorePassword) { - this.keystorePassword = keystorePassword; + public void setSslKeystorePassword(String sslKeystorePassword) { + this.sslKeystorePassword = sslKeystorePassword; + } + + public String getSignatureKeystorePath() { + return signatureKeystorePath; + } + + public void setSignatureKeystorePath(String signatureKeystorePath) { + this.signatureKeystorePath = signatureKeystorePath; + } + + public String getSignatureKeystorePassword() { + return signatureKeystorePassword; + } + + public void setSignatureKeystorePassword(String signatureKeystorePassword) { + this.signatureKeystorePassword = signatureKeystorePassword; } public String getWorkDirectory() { diff --git a/src/main/java/net/identio/server/model/RequestType.java b/src/main/java/net/identio/server/model/ProtocolType.java similarity index 96% rename from src/main/java/net/identio/server/model/RequestType.java rename to src/main/java/net/identio/server/model/ProtocolType.java index 67dd85b..a27dc98 100644 --- a/src/main/java/net/identio/server/model/RequestType.java +++ b/src/main/java/net/identio/server/model/ProtocolType.java @@ -19,6 +19,6 @@ License, or (at your option) any later version. */ package net.identio.server.model; -public enum RequestType { +public enum ProtocolType { SAML, OAUTH } diff --git a/src/main/java/net/identio/server/model/SamlIdpConfiguration.java b/src/main/java/net/identio/server/model/SamlIdpConfiguration.java index e5a8046..fd26f1d 100644 --- a/src/main/java/net/identio/server/model/SamlIdpConfiguration.java +++ b/src/main/java/net/identio/server/model/SamlIdpConfiguration.java @@ -26,30 +26,12 @@ public class SamlIdpConfiguration { private String organizationUrl; private String contactPersonSurname; private String contactPersonEmail; - private String keystore; - private String keystorePassword; private boolean allowUnsecureRequests; private boolean certificateCheckEnabled; private int tokenValidityLength; private int allowedTimeOffset; private String spMetadataDirectory; - public String getKeystore() { - return keystore; - } - - public void setKeystore(String keystore) { - this.keystore = keystore; - } - - public String getKeystorePassword() { - return keystorePassword; - } - - public void setKeystorePassword(String keystorePassword) { - this.keystorePassword = keystorePassword; - } - public boolean isCertificateCheckEnabled() { return certificateCheckEnabled; } diff --git a/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java b/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java index 3544a1d..4507a78 100644 --- a/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java +++ b/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java @@ -23,6 +23,7 @@ License, or (at your option) any later version. import com.fasterxml.jackson.annotation.JsonInclude.Include; import net.identio.server.model.ErrorStatus; +import net.identio.server.model.ProtocolType; import net.identio.server.model.State; @JsonInclude(Include.NON_NULL) @@ -32,7 +33,8 @@ public class AuthSubmitResponse { private ErrorStatus errorStatus; private String destinationUrl; private String relayState; - private String samlResponse; + private String response; + private ProtocolType protocolType; private String challengeType; private String challengeValue; @@ -72,12 +74,21 @@ public AuthSubmitResponse setRelayState(String relayState) { return this; } - public String getSamlResponse() { - return samlResponse; + public String getResponse() { + return response; } - public AuthSubmitResponse setSamlResponse(String samlResponse) { - this.samlResponse = samlResponse; + public AuthSubmitResponse setResponse(String response) { + this.response = response; + return this; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public AuthSubmitResponse setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; return this; } diff --git a/src/main/java/net/identio/server/mvc/common/AuthentController.java b/src/main/java/net/identio/server/mvc/common/AuthentController.java index 1369ce3..4d29cca 100644 --- a/src/main/java/net/identio/server/mvc/common/AuthentController.java +++ b/src/main/java/net/identio/server/mvc/common/AuthentController.java @@ -81,8 +81,8 @@ public AuthSubmitResponse authenticationSubmit(HttpServletRequest httpRequest, return new AuthSubmitResponse().setState(State.RESPONSE) .setDestinationUrl(result.getArValidationResult().getResponseUrl()) - .setRelayState(result.getArValidationResult().getRelayState()) - .setSamlResponse(result.getResponseData()); + .setRelayState(result.getArValidationResult().getRelayState()).setResponse(result.getResponseData()) + .setProtocolType(result.getArValidationResult().getProtocolType()); } // Default response: authentication failed @@ -143,5 +143,5 @@ public ApiErrorResponse handleValidationException(ValidationException e) { public ApiErrorResponse handleServletRequestBindingException(ServletRequestBindingException e) { return new ApiErrorResponse("error.mssing.parameter", e.getMessage()); } - + } diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index 73a0efa..21c1dc0 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -19,6 +19,7 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.oauth; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -64,9 +65,13 @@ public String authorizeRequest(@RequestParam("response_type") String responseTyp LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); // Scopes are separated by a space - List scopesArray = Arrays.asList(scopes.split(" ")); - OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesArray, state); + List scopesList = new ArrayList<>(); + if (scopes != null) { + scopesList = Arrays.asList(scopes.split(" ")); + } + + OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesList, state); ValidationResult result = validationService.validateAuthentRequest(request, identioSession); diff --git a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java new file mode 100644 index 0000000..f0d8096 --- /dev/null +++ b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java @@ -0,0 +1,68 @@ +/* + This file is part of Ident.io + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.service.authorization; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import net.identio.server.model.AuthorizationScope; +import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; +import net.identio.server.service.authorization.exceptions.UnknownScopeException; +import net.identio.server.service.configuration.ConfigurationService; + +@Service +public class AuthorizationService { + + private HashMap scopes; + + @Autowired + public AuthorizationService(ConfigurationService configurationService) { + + scopes = new HashMap<>(); + + for (AuthorizationScope scope : configurationService.getConfiguration().getAuthorizationConfiguration().getScopes()) { + scopes.put(scope.getName(), scope); + } + + } + + public List getScopes(List scopeNames) throws UnknownScopeException, NoScopeProvidedException { + + List scopeList = new ArrayList<>(); + + if (scopeNames.isEmpty()) { + throw new NoScopeProvidedException("Scope list is empty"); + } + + for (String scopeName : scopeNames) { + if (scopes.containsKey(scopeName)) { + scopeList.add(scopes.get(scopeName)); + } else { + throw new UnknownScopeException("Unknown scope: " + scopeName); + } + } + return scopeList; + } + +} diff --git a/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java b/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java new file mode 100644 index 0000000..5062bd8 --- /dev/null +++ b/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java @@ -0,0 +1,14 @@ +package net.identio.server.service.authorization.exceptions; + +public class NoScopeProvidedException extends Exception { + + private static final long serialVersionUID = -7605232415378961869L; + + public NoScopeProvidedException(String s) { + super(s); + } + + public NoScopeProvidedException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java b/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java new file mode 100644 index 0000000..eb35543 --- /dev/null +++ b/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java @@ -0,0 +1,14 @@ +package net.identio.server.service.authorization.exceptions; + +public class UnknownScopeException extends Exception { + + private static final long serialVersionUID = 3426051627524438530L; + + public UnknownScopeException(String s) { + super(s); + } + + public UnknownScopeException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java index b285899..f1413c4 100644 --- a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java +++ b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java @@ -105,7 +105,7 @@ public ArrayList determineTargetAuthLevel(AuthRequestValidationResult // Otherwise, we apply the auth level specified in the configuration for // this application // If none is specified, we apply the default authent level - ArrayList requestedAuthLevels = new ArrayList<>(); + List requestedAuthLevels = new ArrayList<>(); String requestedComparison = null; ArrayList targetAuthLevels = new ArrayList<>(); diff --git a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java index ebfbca8..9e251e7 100644 --- a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java +++ b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java @@ -88,13 +88,13 @@ private void setDefaultValues() throws IOException { // Global configuration default values - if (configuration.getGlobalConfiguration().getKeystorePassword() == null) { - configuration.getGlobalConfiguration().setKeystorePassword("password"); + if (configuration.getGlobalConfiguration().getSslKeystorePassword() == null) { + configuration.getGlobalConfiguration().setSslKeystorePassword("password"); } - if (configuration.getGlobalConfiguration().getKeystorePath() == null) { + if (configuration.getGlobalConfiguration().getSslKeystorePath() == null) { configuration.getGlobalConfiguration() - .setKeystorePath(Paths.get(configDirectoryPath, "ssl-certificate.p12").toString()); + .setSslKeystorePath(Paths.get(configDirectoryPath, "ssl-certificate.p12").toString()); } if (configuration.getGlobalConfiguration().getPort() == 0) { @@ -105,6 +105,15 @@ private void setDefaultValues() throws IOException { } } + if (configuration.getGlobalConfiguration().getSignatureKeystorePath() == null) { + configuration.getGlobalConfiguration() + .setSignatureKeystorePath(Paths.get(configDirectoryPath, "default-sign-certificate.p12").toString()); + } + + if (configuration.getGlobalConfiguration().getSslKeystorePassword() == null) { + configuration.getGlobalConfiguration().setSslKeystorePassword("password"); + } + if (configuration.getGlobalConfiguration().getWorkDirectory() == null) { configuration.getGlobalConfiguration().setWorkDirectory(Paths.get(configDirectoryPath, "work").toString()); } @@ -114,20 +123,11 @@ private void setDefaultValues() throws IOException { } // SAML IDP configuration default values - - if (configuration.getSamlIdpConfiguration().getKeystore() == null) { - configuration.getSamlIdpConfiguration() - .setKeystore(Paths.get(configDirectoryPath, "idp-default-sign-certificate.p12").toString()); - } - + if (configuration.getSamlIdpConfiguration().getTokenValidityLength() == 0) { configuration.getSamlIdpConfiguration().setTokenValidityLength(3); } - - if (configuration.getSamlIdpConfiguration().getKeystorePassword() == null) { - configuration.getSamlIdpConfiguration().setKeystorePassword("password"); - } - + if (configuration.getSamlIdpConfiguration().getSpMetadataDirectory() == null) { configuration.getSamlIdpConfiguration() .setSpMetadataDirectory(Paths.get(configDirectoryPath, "trusted-sp").toString()); diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java new file mode 100644 index 0000000..818f832 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -0,0 +1,231 @@ +/* + This file is part of Ident.io + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.service.oauth; + +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableEntryException; +import java.security.cert.CertificateException; +import java.security.interfaces.RSAKey; +import java.util.Enumeration; +import java.util.List; +import java.util.UUID; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; + +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.AuthRequestValidationResult; +import net.identio.server.model.ErrorStatus; +import net.identio.server.model.OAuthClient; +import net.identio.server.model.OAuthInboundRequest; +import net.identio.server.model.ProtocolType; +import net.identio.server.model.AuthorizationScope; +import net.identio.server.model.UserSession; +import net.identio.server.service.authorization.AuthorizationService; +import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; +import net.identio.server.service.authorization.exceptions.UnknownScopeException; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.oauth.exceptions.ClientNotFoundException; +import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; +import net.identio.server.service.oauth.model.OAuthGrants; +import net.identio.server.service.oauth.model.OAuthResponseType; + +@Service +public class OAuthService { + + private static final Logger LOG = LoggerFactory.getLogger(OAuthService.class); + + @Autowired + private OAuthClientRepository clientRepository; + @Autowired + private AuthorizationService authorizationService; + + private ConfigurationService configurationService; + + private RSAKey signingKey; + + @Autowired + public OAuthService(ConfigurationService configurationService) throws InitializationException { + this.configurationService = configurationService; + + // Cache signing certificate + try (FileInputStream fis = new FileInputStream( + configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePath())) { + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(fis, configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePassword() + .toCharArray()); + + Enumeration aliases = ks.aliases(); + + if (aliases == null || !aliases.hasMoreElements()) { + throw new InitializationException("Keystore doesn't contain a certificate"); + } + + String alias = aliases.nextElement(); + + KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, + new KeyStore.PasswordProtection(configurationService.getConfiguration().getGlobalConfiguration() + .getSignatureKeystorePassword().toCharArray())); + + signingKey = (RSAKey) keyEntry.getPrivateKey(); + + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException + | UnrecoverableEntryException ex) { + throw new InitializationException("Could not initialize OAuth Service", ex); + } + } + + public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) + throws ClientNotFoundException, InvalidRedirectUriException { + + AuthRequestValidationResult result = new AuthRequestValidationResult(); + + // Fetch client + OAuthClient client = clientRepository.getOAuthClientbyId(request.getClientId()); + + // Verify redirectUri + checkRedirectUri(client, request.getRedirectUri()); + + // Validate response type value + if (!checkValidResponseTypes(request.getResponseType())) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_RESPONSE_TYPE_NOT_SUPPORTED); + } + + // Validate scope value + List scopes; + try { + scopes = authorizationService.getScopes(request.getScopes()); + } catch (UnknownScopeException | NoScopeProvidedException e) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_INVALID_SCOPE); + } + + // Validate client authorization regarding allowed scopes and response + // types + if (!checkClientAuthorization(client, request.getResponseType(), request.getScopes())) { + return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); + } + + result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(request.getRedirectUri()) + .setProtocolType(ProtocolType.OAUTH).setRelayState(request.getState()).setRequestedScopes(scopes) + .setResponseType(request.getResponseType()); + + return result; + } + + public String generateSuccessResponse(AuthRequestValidationResult result, UserSession userSession) { + + // http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600 + StringBuilder responseBuilder = new StringBuilder(); + + responseBuilder.append(result.getResponseUrl()).append("#"); + + // Determine expiration time of the authorization + int expirationTime = -1; + for (AuthorizationScope scope : result.getRequestedScopes()) { + if (expirationTime == -1 || scope.getExpirationTime() < expirationTime) { + expirationTime = scope.getExpirationTime(); + } + } + + responseBuilder.append("expires_in=").append(expirationTime); + + // Calculate scope string + StringBuilder scopeBuilder = new StringBuilder(); + for (AuthorizationScope scope : result.getRequestedScopes()) { + scopeBuilder.append(scope.getName()).append(' '); + } + + scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma + + if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { + responseBuilder.append("&token_type=Bearer"); + + DateTime now = new DateTime(DateTimeZone.UTC); + + String accessToken = JWT.create().withIssuer(configurationService.getPublicFqdn()) + .withExpiresAt(now.plusSeconds(expirationTime).toDate()).withIssuedAt(now.toDate()) + .withSubject(userSession.getUserId()).withAudience(result.getSourceApplicationName()) + .withJWTId(UUID.randomUUID().toString()).withClaim("scope", scopeBuilder.toString()) + .sign(Algorithm.RSA256(signingKey)); + + responseBuilder.append("&access_token=").append(accessToken); + } + + if (result.getRelayState() != null) { + responseBuilder.append("&state=").append(result.getRelayState()); + } + + System.out.println(responseBuilder.toString()); + + return responseBuilder.toString(); + } + + private boolean checkValidResponseTypes(String responseType) { + + // Only valid response types are "token" and "code" + if (!responseType.equals(OAuthResponseType.CODE) && !responseType.equals(OAuthResponseType.TOKEN)) { + LOG.error("ResponseType not supported: {}", responseType); + return false; + } + + return true; + } + + private void checkRedirectUri(OAuthClient client, String redirectUri) throws InvalidRedirectUriException { + + if (!client.getResponseUri().contains(redirectUri)) { + String message = "Unknown redirectUri: " + redirectUri; + LOG.error(message); + throw new InvalidRedirectUriException(message); + } + } + + private boolean checkClientAuthorization(OAuthClient client, String responseType, List requestedScopes) { + + if (!responseType.equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains(OAuthGrants.IMPLICIT) + || !responseType.equals(OAuthResponseType.CODE) + && client.getAllowedGrants().contains(OAuthGrants.AUTHORIZATION_CODE)) { + + LOG.error("Client not authorized to use the response type: {}", responseType); + return false; + } + + if (!client.getAllowedScopes().containsAll(requestedScopes)) { + + LOG.error("Client not authorized to use the requested scope"); + return false; + } + + return true; + + } + +} diff --git a/src/main/java/net/identio/server/service/oauth/OauthService.java b/src/main/java/net/identio/server/service/oauth/OauthService.java deleted file mode 100644 index 841795f..0000000 --- a/src/main/java/net/identio/server/service/oauth/OauthService.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.service.oauth; - -import java.util.List; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Service; - -import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.OAuthClient; -import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.oauth.exceptions.ClientNotFoundException; -import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; -import net.identio.server.service.oauth.model.OAuthGrants; -import net.identio.server.service.oauth.model.OAuthResponseType; - -@Service -@Scope("singleton") -public class OauthService { - - private OAuthClientRepository clientRepository; - - @Autowired - public OauthService(OAuthClientRepository clientRepository) { - this.clientRepository = clientRepository; - } - - public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) - throws ClientNotFoundException, InvalidRedirectUriException { - - AuthRequestValidationResult result = new AuthRequestValidationResult(); - - // Fetch client - OAuthClient client; - - client = clientRepository.getOAuthClientbyId(request.getClientId()); - - // Verify redirectUri - if (!client.getResponseUri().contains(request.getRedirectUri())) { - throw new InvalidRedirectUriException("Unknown redirectUri" + request.getRedirectUri()); - } - - // Validate response type value - if (!checkValidResponseTypes(request.getResponseType())) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_RESPONSE_TYPE_NOT_SUPPORTED); - } - // Validate scope value - if (!checkValidScopes(request.getScopes())) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_INVALID_SCOPE); - } - - // Validate requested response type - if (!request.getResponseType().equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains(OAuthGrants.IMPLICIT) - || !request.getResponseType().equals(OAuthResponseType.CODE) - && client.getAllowedGrants().contains(OAuthGrants.AUTHORIZATION_CODE)) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); - } - - - // Validate requested scopes - if (!client.getAllowedScopes().containsAll(request.getScopes())) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); - } - - return result; - } - - private boolean checkValidResponseTypes(String responseType) { - - // Only valid response types are "token" and "code" - return responseType.equals(OAuthResponseType.CODE) || responseType.equals(OAuthResponseType.CODE); - } - - private boolean checkValidScopes(List scopes) { - - // TODO: to be implemented - - return true; - } - -} diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java index 0886a74..4ab6c8d 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -41,7 +41,7 @@ public FileOAuthClientRepository(ConfigurationService configurationService) thro OAuthClientFile clientFile = (OAuthClientFile) yaml.load(is); - for (OAuthClient client : clientFile.getOauthClients()) { + for (OAuthClient client : clientFile.getoAuthClients()) { clients.put(client.getClientId(), client); } diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java index 67eaac1..0808511 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java @@ -6,13 +6,14 @@ public class OAuthClientFile { - private List oauthClients; + private List oAuthClients; - public List getOauthClients() { - return oauthClients; + public List getoAuthClients() { + return oAuthClients; } - public void setOauthClients(List oauthClients) { - this.oauthClients = oauthClients; + public void setoAuthClients(List oAuthClients) { + this.oAuthClients = oAuthClients; } + } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java index 28220fe..bc1d6bd 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java @@ -1,15 +1,8 @@ package net.identio.server.service.oauth.model; -public enum OAuthGrants { - IMPLICIT("implicit"), AUTHORIZATION_CODE("authorization_code"); +public class OAuthGrants { - private String name; + public static final String IMPLICIT = "implicit"; + public static final String AUTHORIZATION_CODE = "code"; - OAuthGrants(String name) { - this.name = name; - } - - public String toString() { - return this.name; - } } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java index de29bac..29b3ce4 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java @@ -1,15 +1,7 @@ package net.identio.server.service.oauth.model; -public enum OAuthResponseType { - CODE("code"), TOKEN("token"); +public class OAuthResponseType { - private String name; - - OAuthResponseType(String name) { - this.name = name; - } - - public String toString() { - return this.name; - } + public static final String CODE = "code"; + public static final String TOKEN = "token"; } diff --git a/src/main/java/net/identio/server/service/saml/MetadataService.java b/src/main/java/net/identio/server/service/saml/MetadataService.java index 2b6f578..f221334 100644 --- a/src/main/java/net/identio/server/service/saml/MetadataService.java +++ b/src/main/java/net/identio/server/service/saml/MetadataService.java @@ -111,9 +111,9 @@ private void initIdpMetadata() throws TechnicalException, InitializationExceptio // Extract certificate from provided P12 ArrayList certs = new ArrayList<>(); - try (FileInputStream fis = new FileInputStream(config.getSamlIdpConfiguration().getKeystore())) { + try (FileInputStream fis = new FileInputStream(config.getGlobalConfiguration().getSignatureKeystorePath())) { KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(fis, config.getSamlIdpConfiguration().getKeystorePassword().toCharArray()); + ks.load(fis, config.getGlobalConfiguration().getSignatureKeystorePassword().toCharArray()); Enumeration aliases = ks.aliases(); diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index 50a640c..9a35083 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -61,7 +61,7 @@ License, or (at your option) any later version. import net.identio.server.model.AuthSession; import net.identio.server.model.ErrorStatus; import net.identio.server.model.IdentioConfiguration; -import net.identio.server.model.RequestType; +import net.identio.server.model.ProtocolType; import net.identio.server.model.SamlAuthRequestGenerationResult; import net.identio.server.model.SamlInboundRequest; import net.identio.server.model.UserSession; @@ -107,8 +107,8 @@ public SamlService(ConfigurationService configurationService, MetadataService me private void initSigner(IdentioConfiguration config) throws TechnicalException { - String keystoreFile = config.getSamlIdpConfiguration().getKeystore(); - String keystorePassword = config.getSamlIdpConfiguration().getKeystorePassword(); + String keystoreFile = config.getGlobalConfiguration().getSignatureKeystorePath(); + String keystorePassword = config.getGlobalConfiguration().getSignatureKeystorePassword(); boolean isCertificateCheckEnabled = config.getSamlIdpConfiguration().isCertificateCheckEnabled(); LOG.debug("Initializing SAML signer..."); @@ -161,9 +161,9 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req LOG.error("No suitable response endpoint found"); return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_UNKNOWN_ENDPOINT); } - + result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) - .setForceAuthentication(forceAuthn).setRequestType(RequestType.SAML) + .setForceAuthentication(forceAuthn).setProtocolType(ProtocolType.SAML) .setRelayState(request.getRelayState()).setResponseUrl(destinationEndpoint.getLocation()); // Extract the requested authentication level, if any diff --git a/src/main/java/net/identio/server/service/validation/ValidationService.java b/src/main/java/net/identio/server/service/validation/ValidationService.java index ac5cf7f..aad04b5 100644 --- a/src/main/java/net/identio/server/service/validation/ValidationService.java +++ b/src/main/java/net/identio/server/service/validation/ValidationService.java @@ -45,7 +45,7 @@ License, or (at your option) any later version. import net.identio.server.model.ErrorStatus; import net.identio.server.model.InboundRequest; import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.model.RequestType; +import net.identio.server.model.ProtocolType; import net.identio.server.model.SamlAuthMethod; import net.identio.server.model.SamlAuthRequestGenerationResult; import net.identio.server.model.SamlInboundRequest; @@ -56,7 +56,7 @@ License, or (at your option) any later version. import net.identio.server.service.authentication.AuthenticationService; import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; import net.identio.server.service.authpolicy.AuthPolicyService; -import net.identio.server.service.oauth.OauthService; +import net.identio.server.service.oauth.OAuthService; import net.identio.server.service.oauth.exceptions.ClientNotFoundException; import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; import net.identio.server.service.saml.SamlService; @@ -76,7 +76,7 @@ public class ValidationService { private UserSessionService userSessionService; @Autowired - private OauthService oauthService; + private OAuthService oauthService; @Autowired private AuthPolicyService authPolicyService; @@ -99,23 +99,23 @@ public ValidationResult validateAuthentRequest(InboundRequest request, String se AuthRequestValidationResult arValidationResult = null; if (request instanceof SamlInboundRequest) { - arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest)request); - } + arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest) request); + } if (request instanceof OAuthInboundRequest) { try { - arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest)request); + arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest) request); } catch (ClientNotFoundException | InvalidRedirectUriException e) { throw new ValidationException("An error occured when processing the request", e); } } - + validationResult.setArValidationResult(arValidationResult); if (!arValidationResult.isSuccess()) { validationResult.setState(State.RESPONSE); validationResult.setResponseData(generateFatalErrorResponse(arValidationResult)); - + return validationResult; } @@ -125,7 +125,7 @@ public ValidationResult validateAuthentRequest(InboundRequest request, String se validationResult.setTransactionId(transactionData.getTransactionId()); validationResult.setSessionId(userSession.getId()); - + // Determine target auth levels and auth methods ArrayList targetAuthLevels = authPolicyService.determineTargetAuthLevel(arValidationResult); HashSet targetAuthMethods = authPolicyService.determineTargetAuthMethods(targetAuthLevels); @@ -273,7 +273,7 @@ public ValidationResult validateExplicitAuthentication(String transactionId, Str validationResult.setChallengeType(authResult.getChallengeType()); validationResult.setChallengeValue(authResult.getChallengeValue()); break; - + default: String message = "Unknown transaction state"; LOG.error(message); @@ -345,7 +345,7 @@ public SamlAuthRequestGenerationResult initSamlRequest(String transactionId, Str private String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestValidationResult arValidationResult, TransactionData transactionData) throws ValidationException { - if (arValidationResult.getRequestType() == RequestType.SAML) { + if (arValidationResult.getProtocolType() == ProtocolType.SAML) { try { return samlService.generateSuccessResponse(decision, arValidationResult, @@ -358,13 +358,14 @@ private String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestV transactionService.removeTransactionData(transactionData); } } else { - throw new UnsupportedOperationException(); + return oauthService.generateSuccessResponse(arValidationResult, transactionData.getUserSession()); } } - private String generateFatalErrorResponse(AuthRequestValidationResult arValidationResult) throws ValidationException { + private String generateFatalErrorResponse(AuthRequestValidationResult arValidationResult) + throws ValidationException { - if (arValidationResult.getRequestType() == RequestType.SAML) { + if (arValidationResult.getProtocolType() == ProtocolType.SAML) { try { return samlService.generateErrorResponse(arValidationResult); diff --git a/ui/app/index.html b/ui/app/index.html index fbd07fa..e04dedd 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -48,6 +48,7 @@ + diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index 98b6455..c198968 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -35,12 +35,6 @@ // Request the list of authentication methods function init() { - if ($stateParams.transactionId) { - $state.go('error', { - errorCode : 'AUTH_NO_TRANSACTION' - }); - } - vm.submitInProgress = false; vm.methodChoiceEnabled = true; vm.password = null; @@ -107,7 +101,13 @@ data.destinationUrl = $sce .trustAsResourceUrl(data.destinationUrl); - $rootScope.$broadcast('saml.submit.response', data); + if (data.protocolType === 'SAML') { + $rootScope.$broadcast('saml.submit.response', data); + } + if (data.protocolType === 'OAUTH') { + $rootScope.$broadcast('oauth.submit.response', data); + } + return; } diff --git a/ui/app/scripts/directives/oauth-responder.js b/ui/app/scripts/directives/oauth-responder.js new file mode 100644 index 0000000..a4dabd3 --- /dev/null +++ b/ui/app/scripts/directives/oauth-responder.js @@ -0,0 +1,20 @@ +(function() { +'use strict'; + +angular.module('identioUiApp') + .directive('oauthResponder', OauthResponder); + + OauthResponder.$inject = ['$window']; + + function OauthResponder($window) { + return { + replace: true, + scope: {}, + link: function($scope, element, $attrs) { + $scope.$on($attrs.event, function(event, data) { + $window.location.href = data.response; + }); + } + }; + } +})(); \ No newline at end of file diff --git a/ui/app/scripts/directives/saml-responder.js b/ui/app/scripts/directives/saml-responder.js index 5d349a1..07e8094 100644 --- a/ui/app/scripts/directives/saml-responder.js +++ b/ui/app/scripts/directives/saml-responder.js @@ -11,7 +11,7 @@ angular.module('identioUiApp') replace: true, scope: {}, template: '
'+ - ''+ + ''+ ''+ '
', link: function($scope, element, $attrs) { diff --git a/ui/app/views/auth.html b/ui/app/views/auth.html index ae5df41..fb03c63 100644 --- a/ui/app/views/auth.html +++ b/ui/app/views/auth.html @@ -53,3 +53,5 @@
+
+ From aa2ef1fbbce02b95b9e98fde228af3fcaa9a4601 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Fri, 10 Feb 2017 13:28:59 +0100 Subject: [PATCH 010/104] Some small fixes --- ...rtificate.p12 => default-sign-certificate.p12} | Bin .../authorization/AuthorizationService.java | 14 +++++++++++++- .../configuration/ConfigurationService.java | 4 ++-- .../infrastructure/FileOAuthClientRepository.java | 7 ++++++- .../identio/server/service/saml/SamlService.java | 2 ++ 5 files changed, 23 insertions(+), 4 deletions(-) rename sample-config/{idp-default-sign-certificate.p12 => default-sign-certificate.p12} (100%) diff --git a/sample-config/idp-default-sign-certificate.p12 b/sample-config/default-sign-certificate.p12 similarity index 100% rename from sample-config/idp-default-sign-certificate.p12 rename to sample-config/default-sign-certificate.p12 diff --git a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java index f0d8096..6bb46b7 100644 --- a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java +++ b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java @@ -23,6 +23,8 @@ License, or (at your option) any later version. import java.util.HashMap; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -34,6 +36,8 @@ License, or (at your option) any later version. @Service public class AuthorizationService { + private static final Logger LOG = LoggerFactory.getLogger(AuthorizationService.class); + private HashMap scopes; @Autowired @@ -41,7 +45,15 @@ public AuthorizationService(ConfigurationService configurationService) { scopes = new HashMap<>(); - for (AuthorizationScope scope : configurationService.getConfiguration().getAuthorizationConfiguration().getScopes()) { + List configuredScopes = configurationService.getConfiguration().getAuthorizationConfiguration().getScopes(); + + if (configuredScopes == null) { + return; + } + + LOG.info("Initializing Authorization Service"); + + for (AuthorizationScope scope : configuredScopes) { scopes.put(scope.getName(), scope); } diff --git a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java index 9e251e7..11a30e1 100644 --- a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java +++ b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java @@ -110,8 +110,8 @@ private void setDefaultValues() throws IOException { .setSignatureKeystorePath(Paths.get(configDirectoryPath, "default-sign-certificate.p12").toString()); } - if (configuration.getGlobalConfiguration().getSslKeystorePassword() == null) { - configuration.getGlobalConfiguration().setSslKeystorePassword("password"); + if (configuration.getGlobalConfiguration().getSignatureKeystorePassword() == null) { + configuration.getGlobalConfiguration().setSignatureKeystorePassword("password"); } if (configuration.getGlobalConfiguration().getWorkDirectory() == null) { diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java index 4ab6c8d..432a32d 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -28,12 +28,17 @@ public class FileOAuthClientRepository implements OAuthClientRepository { @Autowired public FileOAuthClientRepository(ConfigurationService configurationService) throws InitializationException { - LOG.info("Initializing File OAUth Client Repository"); clients = new HashMap<>(); String clientFilePath = configurationService.getConfiguration().getoAuthServerConfiguration().getClientFile(); + if (clientFilePath == null) { + return; + } + + LOG.info("Initializing File OAUth Client Repository"); + try (FileInputStream is = new FileInputStream(clientFilePath)) { Yaml yaml = new Yaml(new CustomClassLoaderConstructor(OAuthClientFile.class, diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index 9a35083..a6ae346 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -138,6 +138,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req AuthRequestValidationResult result = new AuthRequestValidationResult(); + result.setProtocolType(ProtocolType.SAML); + // Parse the authentication request AuthentRequest ar = null; From 53206a3d25d596572d558f26285bf1d67590d388 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 25 Jul 2017 15:38:20 +0200 Subject: [PATCH 011/104] Version bump and build fixes --- .gitignore | 1 + build.gradle | 20 +++++----- gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 53319 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 46 ++++++++++++----------- gradlew.bat | 8 ++-- ui/package.json | 10 ++--- 7 files changed, 47 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 8ba6445..0f492a8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /build/ /.gradle/ /.settings/ +/.idea/ /.project /.classpath .DS_Store diff --git a/build.gradle b/build.gradle index 399e9dc..5d26ba7 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ buildscript { ext { - springBootVersion = '1.4.0.RELEASE' + springBootVersion = '1.5.4.RELEASE' } repositories { mavenCentral() @@ -15,15 +15,15 @@ buildscript { } plugins { - id 'com.moowork.node' version '0.13' - id 'com.moowork.grunt' version '0.13' - id 'com.github.ben-manes.versions' version '0.13.0' + id 'com.moowork.node' version '0.13' + id 'com.moowork.grunt' version '0.13' + id 'com.github.ben-manes.versions' version '0.15.0' + id 'org.springframework.boot' version '1.5.4.RELEASE' } apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'idea' -apply plugin: 'spring-boot' apply plugin: 'war' apply plugin: 'application' @@ -49,11 +49,11 @@ dependencies { compile("org.springframework.security:spring-security-web:4.1.2.RELEASE") compile('org.apache.commons:commons-pool2:2.4.2') compile('com.github.identio:identio-saml:1.0.2') - compile('com.google.guava:guava:19.0') - compile('com.github.detiber:jradius-client:-SNAPSHOT') + compile('com.google.guava:guava:22.0') + compile('com.github.identio:jradius-client:-SNAPSHOT') providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:${springBootVersion}") - providedRuntime('ch.qos.logback:logback-core:1.1.7') - providedRuntime('ch.qos.logback:logback-classic:1.1.7') + providedRuntime('ch.qos.logback:logback-core:1.2.3') + providedRuntime('ch.qos.logback:logback-classic:1.2.3') testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") } @@ -171,5 +171,5 @@ task release(dependsOn: ['releaseTarGz', 'releaseZip']) { } task wrapper(type: Wrapper) { - gradleVersion = '2.14' + gradleVersion = '4.0' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 941144813d241db74e1bf25b6804c679fbe7f0a3..d3b83982b9b1bccad955349d702be9b884c6e049 100644 GIT binary patch delta 5479 zcmaJ_2{=@3`yYcS`!be^#=h?%YbyI1vhT}S%91TanowkqlPn=Zk|JhMA~D7?Su0Dj zlPo1FSzrFgjJLk|zU%s*>pIuD&pp52y*!IS+YN7)$&1Y((f<^mgM?rP9l5E=q_IH>3$qK#XjPAfV}? zK~SRVCdE8aun;XI-YkrUVL`8n9ZLS?Q+1uVp(;#cSeK~3YR}v$NSdv-9UNI8SUTfh` zxx7{AVr9Z-{;Fuo4@DV#Y(C1nwS?VFSxT>31ZRw}kkAi*%Jeq8j7i)kbLQUI+#`0M z(_`(g%o~MqJIvc>`B$biDRX14MAwbj`Cg6K>z#Sm%7^=9G{=?_e19}b^6tBCEs^<= zxEyL4d1G78_5mX=Z9|VM(c4F{@_9bc$~SKkZ$#op3u~|T%B-WjLwy|UvufAxO2yg+ zO4dI77?;PM;xBv=NfGx&LY2v2WK_q1!S9ou%Ck>JBmV6J^=y7gEFJwP(YgBdJ*=ZF z4Hp(+N(hk>ADbdh{?d4=WAC53mz?`)m%H2;*X6!2dhbRv?Qz-nwq;X%Ml#jC{3xVr zgm7gUH&$*jc>H}Bic=5G@=~Ysck=e*o{~*2;e4qYAm^4c|8eLgtVW-nr z!53X}Otam;$}A{)WwtG==8?PaqF`?&{(`Y*%7-|A8i(vUzqc#nCQF`|@$VEDmenim zzdOzcS>l9N^wZ6&DK7{i%k^gYDeDqxxhQR68$}f(?ex+*^S28NV;o_KSr*uXnUk;w zv(bsttEDkj7S~WImnn{%pD>3?W@g!(kt|K|^JlFR|Fo;PY0c z@EK8Y{@AV%BR5^>;D%cv-aJ9_>XFWX$U)9s_h?-c?yO->qJCxyy-CgfYz__x_K@;j)w~Ib?H$U4bI-8Sx7!~Ae}sqE&S%PMFU0q z`1LS)uhCuQ5RKN=fw`Al5$)>N8EPN&E6;7rIeIOszfnf9TW#zqb41XxZ!PHFNuUZ; z*4UPf3zUDy&w$WY{cIZ^NZ&J8ok_dh<&3ah{^E5TL!q2%c3fD}l^LDLG=e$JQ_R4* zPPON{MOigvojkAa;D$LJ!VH^}a{a{^mNTju!tzl!!mlwgYgJBkFd$Z3cTunwlN$JI z#>=6_N8*++VlsGG#!$vg!lWfEbF}svnRD519jC~j&ZK=1t-_WDWjg3zZkrdy7mh$6 zaC!(t2uP=316DcMP|nAPnf9gh>};R-!ea>W`m8;i%gCZ_nx#)W7`a0g%|I!uLz|*S1 zwr8(x$6deB$9kpWj%^`Xh0K$wRjsZdhw-4SbvK-80Mh^Z?}YLM+;%xXrF|cJieSg{ zs=JEX*i-KJbdK~GvB;h0ychD=lXgq zi=sR+!#(G4L)u{>tCCIhjR^tMzEM>$O35Bf$YY*{N2=|~Qd&Ac<(HGVL(AJ_d{L!% zgahR}OY~D0#jSbN*QQt{d!*B|5uA7f`fLK%_B&0{+O)f^cl-NMnuPuYr zYNu-BFje5w&Z%{*&!)6^C13sRGS#;&7o=O}gP#Ok9~v1#i+tr@5wk3cJ){ z@@iE1)(xDvaGb9`-||VC})@VX3kTcwP3nt#>K1`#Z$YgRRPs&;;`l+nONJ2 zrLj4FvFpXtsQS(P#7Un`^1a8?=Qq(YQVb(PJs#~n=Z1n(VhXpDM3QH!V!U-**4T2a z`rnV_SJ_m)y!dqs9rn;dbe_ek%h>n149g?S$`?nQ<#pPAS0rb*POgU0g{|erJ<+;m zJ$6O$)EPR3G4~&_z3oZXt|yOo-LFeTd51eP%OpAu6(CW2ZZV~qGWlA#hzYTAzU(%8 zGrb2XE}p~w9LtSN49z`nyRcm?^Ow{nJ`A=u!Iur{o-TQQR<6q6pTXnBIj-A>sfdU! zn)+YleG%(*AMQ`1`F1bgHSLG&5gG*6=B-s@^RxON&+A)!BFoJJw)cN=HVY%0HhlAK zdbzo_qEnur&|4Ho(+j5Rt4xDT;Wj1ay~|SSH-X`HN~8b+a$5ks*PDQ>^QbX@wjJ*7 z6^NA@&&V1`YKl!$ne94mj~>P$lLGX*c*|-+n|%t5JneTfPas(1*3M~5s~G>@t>NZw zYBuTuY0Pzt;bb&g)%p%_YTKW|E8QOL`?s5KLd_}%hdUT~F* zC2RtF?}y)qYPxVG*7LbPG9FKp&8hkN{WwB7@qINfk1OFpLp)Vb$cXw$t;_1Kl$x0N z9!|iwRj8hX2ME_EwHfTvo*dkd^V*`luvZy1mJ-ONOXa?Ttl3%Il8B;ty&=0t9U&W^ zwyK4q+REvGR_B#A-WHV3O;_1wl89XRG$+V#=d_`pXnkeKt}l!{ZGGabQWN0+{n^Yo zozsky{CT+x?=gA&v*?2To2a^#A{xZH+T#y4EtXZCTZ@dFHRY0_5uF{HFM0J_-jtqJ z;Tq*!qEWZTVd>I@IXO8Dvje@8OMsDC%tR;3;QY7`LxC%oZ=h1NWtE$}6W^M&?R1#_ z)V^Q=i;mFyH6$#yiYK=rsV+Z6?ejC0(uLW@NEfNNFagQ4O>Me1!cGIo73-bI3GZ{; z^2_U-5mEP)Z9J|lL{@%7axV%D#n3*D{PMHA(1P1p$BO$EexLN5K&FQl;<02QZuLI)E$|1_Y$hpiLqlQxZ|zH@3)#(nidOLmPdG{X}PSzSeaHPzZzqWa|)|b#x1& zw~{RmqcTe?VoQ!)QLE&m59PU-TX7c3)l~7Eh;+dPAKY0>K}JKvW5FrS(t(v;#17L8C4? z^Fh)K`&esMu(r(Ljer2g1H1x%rqJjAoH%4qR`S2cVZi^*Nz(H$Q29mybub@6Ll7`@ z!UdjL4=+Z@KWFcQ^5q~eX;Z_$#{Qc@^DhB%z-T^Xcm=s4eLenPA~?>FL-GN0>0p~F z@!y`jW00Q3AaD@8`N8|&3lq&v21MgvK&3S`(A~nya}XA8;?@u=m`MPbh1S1F@QH~g zgZ=??w<;hGz+b-F1U~_P`~=>7B;YV0uvM0Tp(u|ScK{8Vfd(Z>Fs?vLs~Tag17uh@ zl$x4gUx}IruxX~PEx4;=e$~{33g1LZPEP??1`(FVBB17V2n~`931uIJQ zbi54?9fc8ej%>7lJdteHNeuXL5WuS(EWpz?TB4Cg&`1t~p#Rp!Nz@&~!J$9o2s%}q z5FvHFp?ZP$;Pm0=0GBa|Q8M5L?i7*t3gp2x3B0d3enK`Mdzr!u!IUxJ$$_-2tR{y} zsQ|-v;(%S^xpW6Z27y?CQ(lS0$uA26c$I?=C~6lVSk7=aIL=88ffzDCAiN~tJu3pZ z(wZKi?jTnGPmcwGr1Qqg8CY``1Z+Xz!E*ZBQXvp9)jt;|y4D%E)geS!=Rj2l9O~=> zyzSs7zJCSZQ(b`RGESh^6%MF&(h~KCop30pJ5Zg>4UJpp$pc+5S%lzf5JGJygx63WG;CMY_9-MHym1*0E{Q99Tbt^ zouoIDcu!0Mz3Uz1LdO4;(sM2)H(i0C#&hiMVP|H(Y#J?IXZ$ z4>Q40xX_G+3%Ii3U>8y)an$e#99s3i!y4HOhXz-GkxTtao222BkgryPp8g$$J~-63 znozT<8iqe9Y7Vf?FM;*C26|Q_A$Qk+V18hz?{K1!^~0fz^#FIjE+J$|n0E{nIDD_b zu;oaIvo8ol$p$7s22U&`$;X5QtnvyhkUC+p{O>2_FA@{o{~G+j$R6Q6XzP&w13B*K A8~^|S delta 5809 zcma)Ac|6qJ_aBq(v2SCUY$3+JM~PxG_Uv0JLiR9r!elQ*d`N|;ELpPiXlz-=gisV& zvSybhkF8R_j~P#W=llKVcVDl0-TONCectDsd(S<0?gyWHEc)3o1|z*=#q!mPjgZ2FKv{ve$WkwyIEguYjV*zZXbdO)0PiZG~V zg!({&XGePT%bELfXpj)K%AKmv*OEY z&i3m@rek|R&od)k-56@9>$lstU>-DLZ*}t-g^VO3u?Aj1jH8mrsTvq8XAgDIMwirX zsdhT5o%2=S>%d=#?Leg`y$PdEA!|(w{{8#ezWu9{zkcj<+&b8^ZkI}Y9)v`)q7+@_Cv^m8&#ZPA3_Jw#x7r#n4R9rHYbm<-m75|s}E zHFs(pwx%8lU0W&nG3ZpNJn^(xo1&q`?b?B>{vUj@B*x)Bo?<9Q6^Ro+w!i(q? zYQYkIvwRh|IT}x$3yLujwbDIWB5@q40t=7oG_AK_l?dO>Jg#l~z zT5HMsN}IlQ>}BsohoEiyvXR336|@&k(x#R}PXraTSmi%KuXeFt7+3WGD^#m~su z4SKjnXGA7B*QEaAvQ&{Wh&KN=F`iq<=2u1@USRjq$-<0U#jW~`g^YZ4RaXF`O466; zg~2u&XAg(_RU5kg?Y@a~w;8B{b!>PjYyh%e@sAH|W2fygdFMu7*sJ3O)ZU_b_=@+m z@%Z{DGpsy0k=CKH{r=pqFdSmd@6o0{&27VC&F?lPn+G>l!;R2-_~bnub-yo+4};z6!^hLy)d?Ir=mr}P5Pr?L!Gb{a$Vum0fa4~hzXuA`E6| zrn2Z7le-c$mrFQ(JnuU*@r9*_;5^()7UY_1QgWDR{idrM^WjNzPXa6CzRkL}>)bA( zxOP%AirWI^$|E&vNLAt0m*&4y$ldVj^haK<8&)xQYtPQ4GFx;T+@x31eU!StevtD` zdcl}1OX*hT$ZZ-1B^g@)gFM?mDfPNV7~!LqvNkQ+X+FK2tQP&XL1aP?zVTqJGTBU8 zlt0q5Y=udavDT&Z>@7z1uRpCc2LC}SBx@#Y96&Ms2PgNss1v2tvkMlcE_m58uk4k7 zic(tyGViT-sYZ+3&oz{Ol0LdJc8aYsMd}pn-Ow&mW=_qG;OLz@6BvOyHB?-ry6x*- z&M~&}*1ulTrp&F=?k6lt*nhXf<=Qdc$5S<<*EYRQuQ7U+htvVAtaKVn6-~ zB_g@IHMkMNE!G>!CNf??!E!*Xx>8Kntc=M;@S7*e@y#%5-B$hc7# zQ=U$1H4u{B;BYl1**CCljQ$rDX@$)Xmcd$7e}Tml%VVF$bBFpM*nNf~! z6K>=2v@e(CN>P>Uc=b@B zq~val^QH+MU&72RIux3dIBkj!h3BN;oHemLxCO_bq1^b5DmvTSGYQ6_qOsEWcQNH1 z8|KD8AJN%zWKJ?IWy*%?&3oZDvN@ZN<99d0TG1l0d>tFe)4?L~4KxgiRtcBTuQA>> zV^)ZlvDd|nd<%-kqBMKaep;<5dcXlvuzgG3v>n*Wz-z@V6c&j1I%Kd3p*&rbYCVkQ zX-7oiGPDb@Rh}As{0IF&3-SAY6yJq~@j2YQSrcb!%kA9vpQ_C+?p$}bRtS}kO%H2B zEGsYvkIT^SK8@@&+bxZJo10!ZiuuXh{vNN}LyJ{?A<5>yDLv(^ICjs!g3Bj^?&%tL z<*LR|V0zPacX4rScJ|xx{BTsQzCmUZLtX%u-RnCown3h6t0<)I@uoBC<|jm&hk;*z zV9SePRxh3U&mQOo7=?fDd;jPBb-Aa%JrKT=IOjUVk?GN6&so@{LBsU)}E(&rys>WzB$k#}D( zrsoSu!ytd*iPp^$Bg%FZ5#boJ$9KiPBTbBWv#NA= zo=Rmpeq&(R?)nSH;cbiyKFfJC5U zL~!96JxlhA7Jty4b4FE(g`X&)-OG=+z4MQI6VA{c&%0KZHlAmgtyX#E8VWJq zK4~_NkBx89L#-t=%#TuHie~5=b$rOPlR2t8oQ5-$RuR0<_u|+Vp+9vzY2^D(>NMp| z3+c_%7WgOFrFv!9Qxr~28=S!*xz~OAuO;q5QSlK1Ha3ozmHvc3_S3I~k|E2fx@~sQ- zE~*KEqO2BQM0yGBsVnQ(pReglj|@o$yEl=a+LVu&+WNM<=PzqbrLu*^i%NRzOt%-= zgtdHiBVQe`m2lN8#B@$LMV7CY4nCS)?g?iR@kn6v9u6RrOPKvJai-g=0aY_|5JXoh zW=a3rJIr$on{h6{qFZ*Y@}18Qe#>NU3+1>$7@|C+m~V!2fzFS=W4$_Dx41l-jLwJs z7&0P4ZOgstRr<-T^G>Rpt%lch$(YSaYHms3*c zWSdsK*Olz_XZ&RWXTEnI7QHlDf3I3oHk`Jmpcl}IOy4o|dU9s|gwa`@4MijQ2sER4RHJjm zWW!kzk?$-wb~oN4fFZS^!OJK-Wm0d*6PO6;%u)NoyZej0Uzq2!upiaqR994ao-FieTdMLpIog?BL*>a8ICTR2 zKi$kn>l*8>@%9gDamM8a+ZYFjb+nkpOe#nG$_TzFCzqzfq~6cdF;M>GnkulkZPBZ- zdtp-5Q9NiJn|5+4bVgw*o4G7!mOPPuaIhi^+ z1q<&0dSe+m8HG79M0dZgfs|;SfwZoEm(B-+zOK(=V!h&BZwzYZp#Kq@HE7Gu8~3&k zv;`*vdTseIhU%W}{7j8o>0&M%4i0?vpDl{IPa2oQV(%gyUqL;#_x&F^ddaI)%d3=y z2NWtMruplqeB9%gQZp(Nmbe6|yZ!up#QANq?=qPh8{30R#sPOtk&G6Rz(9AIdEXA? zDXf_1rfbJ}`l}<7>2L%7FD^*6>$6TXqK0oWd=>Ow+T<6PJ4tn{Imu6^B^VkDT5^Y< zuQ0pFxRsH-vd%E^J=URp`t66a|n{ zCRwfTTuFphlewjm5wRKWywt?eOJCk&#L-y5nWGU`$N&XVwvO39(pZgnPeqh<+ zdyr6k#EeQRWFgLO=58Fx=AKO+jb0bjk`remN}xwJ;>y;KWIL9}o@~ z)u0`3A0>JPDYJngBjc%@1&P&=F#KLw^-@n4J4y znIUE70nWFbB@mK)5FsJlXCe@aGxGp_ZFIz)m}rATCD;ja#&%8u0m+krgrJ2J1hRuK z2o}Jr{fGe54u^8`69_8Wxrn5_pbRZfko{~ICXi|m{Vg;IhA7AhfgngoZz%)nZQOue z2b`!J-T{X`L=u$CI|K<~|EaA1z48FC*&$0XKvH2z4EUNKd3{)Lg@{HHad2puCBcZa zB?HidBd+i7$_o;Z=FA6R2PemWc!2&?Ob7%F=69=!aIyp5*}?(tPC5eca0c8fLSsDY ziAm~q4M^(bAslL;yb}!f8nF3>3;5hAOq4O;;ZPw*;DnOkeO)w#q%6w+XZ+2 z>~FHe|Tq6GAv*@5yNqDPB@^k22WTSyNik|iPe=>{rr z1LAHR09Q8=e2&BA7an{$#(@V+l?0sTL12IF&JAFWz})WamAxSA80el73AoPhw<{aI zOut?EZ2v)I8dUHEEgXI_{I}Iad<-Ng&;|1TW)}$Qx|9l@k%#o)Blce;*w;j`-vlgVRMhK%L(>xpgz-JHL|F?cLnebV0pOsANM_5ZHt-CLPZW%g^jNPwAt;-? z;U!qrdgrv73Iemh_(*{>c}H$j0^E6Y68~8z5A!fcc*e{QtT1p|2t_wtL7YtwOo3*&qk4~eC~Do}wN zkmxy1w05Zv4jry0kkD2i{~wnDh|0sm75)JdohBhVUJp$5X%R`p`{B^Fmjn{G{-aZp i0LnBQ39{~fVZy?ZUSxmRY9hv3z-vvG^6INY;r{_ \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -30,6 +48,7 @@ die ( ) { cygwin=false msys=false darwin=false +nonstop=false case "`uname`" in CYGWIN* ) cygwin=true @@ -40,26 +59,11 @@ case "`uname`" in MINGW* ) msys=true ;; + NONSTOP* ) + nonstop=true + ;; esac -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -85,7 +89,7 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then diff --git a/gradlew.bat b/gradlew.bat index aec9973..f6d5974 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -8,14 +8,14 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome @@ -46,7 +46,7 @@ echo location of your Java installation. goto fail :init -@rem Get command-line arguments, handling Windowz variants +@rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args if "%@eval[2+2]" == "4" goto 4NT_args diff --git a/ui/package.json b/ui/package.json index 9630c6f..48e855a 100644 --- a/ui/package.json +++ b/ui/package.json @@ -13,18 +13,18 @@ "grunt-contrib-concat": "^1.0.1", "grunt-contrib-connect": "^1.0.2", "grunt-contrib-copy": "^1.0.0", - "grunt-contrib-cssmin": "^1.0.1", + "grunt-contrib-cssmin": "^2.2.0", "grunt-contrib-htmlmin": "^2.0.0", - "grunt-contrib-imagemin": "^1.0.1", + "grunt-contrib-imagemin": "^2.0.1", "grunt-contrib-jshint": "^1.0.0", - "grunt-contrib-uglify": "^2.0.0", + "grunt-contrib-uglify": "^3.0.1", "grunt-contrib-watch": "^1.0.0", "grunt-filerev": "^2.3.1", "grunt-google-cdn": "^0.4.3", "grunt-karma": "^2.0.0", "grunt-newer": "^1.2.0", - "grunt-ng-annotate": "^2.0.2", - "grunt-svgmin": "^3.3.0", + "grunt-ng-annotate": "^3.0.0", + "grunt-svgmin": "^4.0.0", "grunt-usemin": "^3.1.1", "grunt-wiredep": "^3.0.1", "jshint-stylish": "^2.2.1", From 4b60eb52f86b12a3ce8acf4db4517231fd95cc39 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 25 Jul 2017 17:26:20 +0200 Subject: [PATCH 012/104] Fixed Hashbang path update in ui-router --- .../java/net/identio/server/mvc/common/PreAuthController.java | 2 +- .../identio/server/mvc/saml/AssertionConsumerController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/common/PreAuthController.java b/src/main/java/net/identio/server/mvc/common/PreAuthController.java index eb36a17..5e6de88 100644 --- a/src/main/java/net/identio/server/mvc/common/PreAuthController.java +++ b/src/main/java/net/identio/server/mvc/common/PreAuthController.java @@ -81,7 +81,7 @@ public String checkTransparentAuthentication(HttpServletRequest httpRequest, Htt HttpUtils.setSessionCookie(httpResponse, result.getSessionId(), configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - return "redirect:/#/auth/" + validationResult.getTransactionId(); + return "redirect:/#!/auth/" + validationResult.getTransactionId(); } } } diff --git a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java index 7bcab1e..9fcdd3c 100644 --- a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java @@ -85,7 +85,7 @@ public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletRespon HttpUtils.setSessionCookie(httpResponse, result.getSessionId(), configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - return "redirect:/#/auth/" + result.getTransactionId(); + return "redirect:/#!/auth/" + result.getTransactionId(); } } From 7c0ece528e56fc57edcc75de992c74d9f44b2a88 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 25 Jul 2017 17:28:19 +0200 Subject: [PATCH 013/104] Fixed $http calls that don't provide .success() or .error() methods anymore --- ui/app/scripts/controllers/authController.js | 36 +++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index c198968..6973808 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -26,7 +26,7 @@ vm.methods = []; vm.samlMethods = []; - + vm.updateMethod = updateMethod; vm.submit = submit; vm.samlSpSubmit = samlSpSubmit; @@ -34,31 +34,31 @@ // Request the list of authentication methods function init() { - + vm.submitInProgress = false; vm.methodChoiceEnabled = true; vm.password = null; vm.error = null; - AuthService.getAuthMethods($stateParams.transactionId).success( - function(response) { + AuthService.getAuthMethods($stateParams.transactionId).then( + function(successResponse) { vm.methods = []; vm.samlMethods = []; - for (var i = 0; i < response.length; i++) { + for (var i = 0; i < successResponse.data.length; i++) { - if (response[i].type === 'saml') { - vm.samlMethods.push(response[i]); + if (successResponse.data[i].type === 'saml') { + vm.samlMethods.push(successResponse.data[i]); } else { - vm.methods.push(response[i]); + vm.methods.push(successResponse.data[i]); } } vm.selectedItem = vm.methods[0]; $state.go('auth.' + vm.methods[0].type); - }).error(function(error) { + }, function(errorResponse) { $state.go('error', { - errorCode : error.errorCode + errorCode : errorResponse.errorCode }); }); } @@ -74,8 +74,8 @@ AuthService.submitAuth($stateParams.transactionId, vm.selectedItem.name, vm.login, vm.password, - vm.challengeValue).success(authSubmitSuccessHandler).error( - errorHandler); + vm.challengeValue) + .then(authSubmitSuccessHandler, errorHandler); } function samlSpSubmit(methodName) { @@ -94,7 +94,9 @@ }).error(errorHandler); } - function authSubmitSuccessHandler(data) { + function authSubmitSuccessHandler(response) { + + var data = response.data; if (data.state === 'RESPONSE') { @@ -105,9 +107,9 @@ $rootScope.$broadcast('saml.submit.response', data); } if (data.protocolType === 'OAUTH') { - $rootScope.$broadcast('oauth.submit.response', data); + $rootScope.$broadcast('oauth.submit.response', data); } - + return; } @@ -134,9 +136,9 @@ } } - function errorHandler(data) { + function errorHandler(response) { $state.go('error', { - errorCode : data.errorCode + errorCode : response.data.errorCode }); } } From 242619d547e2470027ca3cd6293c2130413476f6 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 25 Jul 2017 17:28:44 +0200 Subject: [PATCH 014/104] Added missing JWT dependency --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 5d26ba7..a2bcb16 100644 --- a/build.gradle +++ b/build.gradle @@ -51,6 +51,7 @@ dependencies { compile('com.github.identio:identio-saml:1.0.2') compile('com.google.guava:guava:22.0') compile('com.github.identio:jradius-client:-SNAPSHOT') + compile('com.auth0:java-jwt:3.0.2') providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:${springBootVersion}") providedRuntime('ch.qos.logback:logback-core:1.2.3') providedRuntime('ch.qos.logback:logback-classic:1.2.3') From 9a6a81f1cb364bd525b286834cb5da0ef4216f45 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 16:26:46 +0200 Subject: [PATCH 015/104] Removed war module and fixed scope of dependencies Added Http Client dependency for tests --- build.gradle | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index a2bcb16..3db15e6 100644 --- a/build.gradle +++ b/build.gradle @@ -24,7 +24,6 @@ plugins { apply plugin: 'java' apply plugin: 'eclipse-wtp' apply plugin: 'idea' -apply plugin: 'war' apply plugin: 'application' sourceCompatibility = 1.8 @@ -52,10 +51,10 @@ dependencies { compile('com.google.guava:guava:22.0') compile('com.github.identio:jradius-client:-SNAPSHOT') compile('com.auth0:java-jwt:3.0.2') - providedRuntime("org.springframework.boot:spring-boot-starter-tomcat:${springBootVersion}") - providedRuntime('ch.qos.logback:logback-core:1.2.3') - providedRuntime('ch.qos.logback:logback-classic:1.2.3') - testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") + compile('ch.qos.logback:logback-core:1.2.3') + compile('ch.qos.logback:logback-classic:1.2.3') + testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") + testCompile("org.apache.httpcomponents:httpclient:4.5.3") } eclipse { From 9852fd7ba1412cf7d0624c37c0c6db1b3a9d6cdf Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 16:27:26 +0200 Subject: [PATCH 016/104] Switched @Component to @Configuration --- .../java/net/identio/server/boot/BootCustomizationBean.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/identio/server/boot/BootCustomizationBean.java b/src/main/java/net/identio/server/boot/BootCustomizationBean.java index 98ad823..f76625d 100644 --- a/src/main/java/net/identio/server/boot/BootCustomizationBean.java +++ b/src/main/java/net/identio/server/boot/BootCustomizationBean.java @@ -39,14 +39,14 @@ License, or (at your option) any later version. import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; -import org.springframework.stereotype.Component; +import org.springframework.context.annotation.Configuration; import net.identio.server.model.X509AuthMethod; import net.identio.server.service.authentication.x509.X509AuthenticationProvider; import net.identio.server.service.configuration.ConfigurationService; import net.identio.server.utils.SecurityUtils; -@Component +@Configuration public class BootCustomizationBean { private static final Logger LOG = LoggerFactory.getLogger(BootCustomizationBean.class); From 619f6f0aa009e2aa2efcec28f39c88bab3958902 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 16:27:59 +0200 Subject: [PATCH 017/104] Fixed Hashbang notation in redirect to error page --- .../net/identio/server/mvc/common/DefaultErrorController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java b/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java index 861120d..5fac9df 100644 --- a/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java +++ b/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java @@ -31,7 +31,7 @@ public class DefaultErrorController implements ErrorController { @RequestMapping(value = PATH) public String displayErrorPage(String errorId) { - return "redirect:/#/error/" + (errorId != null ? errorId : ""); + return "redirect:/#!/error/" + (errorId != null ? errorId : ""); } public String getErrorPath() { From d1bb8b0618c6925d2c4e4375c201480950bf1bd6 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 16:28:39 +0200 Subject: [PATCH 018/104] As we want to redirect user to an error page, don't throw a 400 or 500 error code --- .../server/mvc/common/GlobalControllerExceptionHandler.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index 506337b..cfa6edf 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -35,19 +35,16 @@ public class GlobalControllerExceptionHandler { @Autowired private DefaultErrorController errorController; - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(ServerException.class) public String handleServerException() { return errorController.displayErrorPage("error.server"); } - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(ValidationException.class) public String handleValidationException() { return errorController.displayErrorPage("error.validation"); } - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(ServletRequestBindingException.class) public String handleServletRequestBindingException() { return errorController.displayErrorPage("error.missing.parameter"); From f0a2f2711322932fa3dc337f1b69c4175b7c3918 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 16:29:17 +0200 Subject: [PATCH 019/104] Fixed a missing check if no SAML metadata is present --- .../server/service/saml/MetadataService.java | 305 +++++++++--------- 1 file changed, 155 insertions(+), 150 deletions(-) diff --git a/src/main/java/net/identio/server/service/saml/MetadataService.java b/src/main/java/net/identio/server/service/saml/MetadataService.java index f221334..c8d3184 100644 --- a/src/main/java/net/identio/server/service/saml/MetadataService.java +++ b/src/main/java/net/identio/server/service/saml/MetadataService.java @@ -28,12 +28,12 @@ License, or (at your option) any later version. import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,216 +62,221 @@ License, or (at your option) any later version. @Scope("singleton") public class MetadataService { - private static final Logger LOG = LoggerFactory.getLogger(MetadataService.class); + private static final Logger LOG = LoggerFactory.getLogger(MetadataService.class); - // Private fields - private Metadata idpMetadata; - private HashMap spValidators = new HashMap<>(); - private HashMap spMetadatas = new HashMap<>(); + // Private fields + private Metadata idpMetadata; + private HashMap spValidators = new HashMap<>(); + private HashMap spMetadatas = new HashMap<>(); - private HashMap> loadedSpFiles = new HashMap<>(); + private HashMap> loadedSpFiles = new HashMap<>(); - // Services - private ConfigurationService configurationService; + // Services + private ConfigurationService configurationService; - @Autowired - public MetadataService(ConfigurationService configurationService) throws InitializationException { + @Autowired + public MetadataService(ConfigurationService configurationService) throws InitializationException { - LOG.debug("Initialization of Metadata Service..."); + LOG.debug("Initialization of Metadata Service..."); - this.configurationService = configurationService; + this.configurationService = configurationService; - try { + try { - initIdpMetadata(); + initIdpMetadata(); - } catch (TechnicalException ex) { - throw new InitializationException("Could not initialize Metadata service", ex); - } - } + } catch (TechnicalException ex) { + throw new InitializationException("Could not initialize Metadata service", ex); + } + } - private void initIdpMetadata() throws TechnicalException, InitializationException { + private void initIdpMetadata() throws TechnicalException, InitializationException { - IdentioConfiguration config = configurationService.getConfiguration(); + IdentioConfiguration config = configurationService.getConfiguration(); - LOG.info("Loading SAML IDP metadata..."); + LOG.info("Loading SAML IDP metadata..."); - // Determine idp endpoint configuration - ArrayList idpEndpoints = new ArrayList<>(); - String idpPostUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/POST"; - String idpRedirectUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/Redirect"; - idpEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_REDIRECT, idpRedirectUrl, true)); - idpEndpoints.add(new Endpoint(2, SamlConstants.BINDING_HTTP_POST, idpPostUrl, false)); + // Determine idp endpoint configuration + ArrayList idpEndpoints = new ArrayList<>(); + String idpPostUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/POST"; + String idpRedirectUrl = configurationService.getPublicFqdn() + "/SAML2/SSO/Redirect"; + idpEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_REDIRECT, idpRedirectUrl, true)); + idpEndpoints.add(new Endpoint(2, SamlConstants.BINDING_HTTP_POST, idpPostUrl, false)); - // Determine sp endpoint configuration - ArrayList spEndpoints = new ArrayList<>(); - String spPostUrl = configurationService.getPublicFqdn() + "/SAML2/ACS/POST"; - spEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_POST, spPostUrl, true)); + // Determine sp endpoint configuration + ArrayList spEndpoints = new ArrayList<>(); + String spPostUrl = configurationService.getPublicFqdn() + "/SAML2/ACS/POST"; + spEndpoints.add(new Endpoint(1, SamlConstants.BINDING_HTTP_POST, spPostUrl, true)); - // Extract certificate from provided P12 - ArrayList certs = new ArrayList<>(); + // Extract certificate from provided P12 + ArrayList certs = new ArrayList<>(); - try (FileInputStream fis = new FileInputStream(config.getGlobalConfiguration().getSignatureKeystorePath())) { - KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(fis, config.getGlobalConfiguration().getSignatureKeystorePassword().toCharArray()); + try (FileInputStream fis = new FileInputStream(config.getGlobalConfiguration().getSignatureKeystorePath())) { + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(fis, config.getGlobalConfiguration().getSignatureKeystorePassword().toCharArray()); - Enumeration aliases = ks.aliases(); + Enumeration aliases = ks.aliases(); - if (aliases == null || !aliases.hasMoreElements()) { - throw new InitializationException("Keystore doesn't contain a certificate"); - } + if (aliases == null || !aliases.hasMoreElements()) { + throw new InitializationException("Keystore doesn't contain a certificate"); + } - String alias = aliases.nextElement(); + String alias = aliases.nextElement(); - certs.add((X509Certificate) (ks.getCertificate(alias))); + certs.add((X509Certificate) (ks.getCertificate(alias))); - } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException ex) { - throw new InitializationException("Could not initialize IDP Metadata", ex); - } + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException ex) { + throw new InitializationException("Could not initialize IDP Metadata", ex); + } - // Allow unsecure requests ? - boolean wantRequestsSigned = !config.getSamlIdpConfiguration().isAllowUnsecureRequests(); + // Allow unsecure requests ? + boolean wantRequestsSigned = !config.getSamlIdpConfiguration().isAllowUnsecureRequests(); - // Generate idp metadata - IdpSsoDescriptor idpDescriptor = IdpSsoDescriptor.getInstance().setWantAuthnRequestsSigned(wantRequestsSigned) - .setSsoEndpoints(idpEndpoints) - .setNameIDFormat(Collections.singletonList(SamlConstants.NAMEID_UNSPECIFIED)) - .setSigningCertificates(certs); + // Generate idp metadata + IdpSsoDescriptor idpDescriptor = IdpSsoDescriptor.getInstance().setWantAuthnRequestsSigned(wantRequestsSigned) + .setSsoEndpoints(idpEndpoints) + .setNameIDFormat(Collections.singletonList(SamlConstants.NAMEID_UNSPECIFIED)) + .setSigningCertificates(certs); - SpSsoDescriptor spDescriptor = SpSsoDescriptor.getInstance().setAuthentRequestSigned(true) - .setAssertionConsumerService(spEndpoints) - .setNameIDFormat(Collections.singletonList(SamlConstants.NAMEID_UNSPECIFIED)) - .setWantAssertionsSigned(false).setSigningCertificates(certs); + SpSsoDescriptor spDescriptor = SpSsoDescriptor.getInstance().setAuthentRequestSigned(true) + .setAssertionConsumerService(spEndpoints) + .setNameIDFormat(Collections.singletonList(SamlConstants.NAMEID_UNSPECIFIED)) + .setWantAssertionsSigned(false).setSigningCertificates(certs); - idpMetadata = MetadataBuilder.getInstance() - .setEntityID(configurationService.getPublicFqdn() + "/SAML2") - .setOrganizationName(config.getSamlIdpConfiguration().getOrganizationName()) - .setOrganizationDisplayName(config.getSamlIdpConfiguration().getOrganizationDisplayName()) - .setOrganizationURL(config.getSamlIdpConfiguration().getOrganizationUrl()) - .setContactName(config.getSamlIdpConfiguration().getContactPersonSurname()) - .setContactEmail(config.getSamlIdpConfiguration().getContactPersonEmail()) - .setIdpSsoDescriptors(Collections.singletonList(idpDescriptor)) - .setSpSsoDescriptors(Collections.singletonList(spDescriptor)).build(); + idpMetadata = MetadataBuilder.getInstance() + .setEntityID(configurationService.getPublicFqdn() + "/SAML2") + .setOrganizationName(config.getSamlIdpConfiguration().getOrganizationName()) + .setOrganizationDisplayName(config.getSamlIdpConfiguration().getOrganizationDisplayName()) + .setOrganizationURL(config.getSamlIdpConfiguration().getOrganizationUrl()) + .setContactName(config.getSamlIdpConfiguration().getContactPersonSurname()) + .setContactEmail(config.getSamlIdpConfiguration().getContactPersonEmail()) + .setIdpSsoDescriptors(Collections.singletonList(idpDescriptor)) + .setSpSsoDescriptors(Collections.singletonList(spDescriptor)).build(); - LOG.info("* {}", idpMetadata.getEntityID()); - } + LOG.info("* {}", idpMetadata.getEntityID()); + } - private void loadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, - UntrustedSignerException, InvalidSignatureException, NoSuchAlgorithmException, IOException { + private void loadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, + UntrustedSignerException, InvalidSignatureException, NoSuchAlgorithmException, IOException { - File file = new File(filename); + File file = new File(filename); - Metadata spMetadata = MetadataBuilder.build(file); + Metadata spMetadata = MetadataBuilder.build(file); - LOG.info("Loading SP Metadata {}: {}", spMetadata.getEntityID(), file.getAbsolutePath()); + LOG.info("Loading SP Metadata {}: {}", spMetadata.getEntityID(), file.getAbsolutePath()); - if (spMetadatas.containsKey(spMetadata.getEntityID())) { - LOG.error("* Metadata ignored: an existing metadata has the same Entity ID"); - return; - } + if (spMetadatas.containsKey(spMetadata.getEntityID())) { + LOG.error("* Metadata ignored: an existing metadata has the same Entity ID"); + return; + } - ArrayList certificates = new ArrayList<>(); + ArrayList certificates = new ArrayList<>(); - for (SpSsoDescriptor descriptor : spMetadata.getSpSsoDescriptors()) { - certificates.addAll(descriptor.getSigningCertificates()); - } + for (SpSsoDescriptor descriptor : spMetadata.getSpSsoDescriptors()) { + certificates.addAll(descriptor.getSigningCertificates()); + } - // Check if the metadatas is valid - Validator validator = new Validator(certificates, - configurationService.getConfiguration().getSamlIdpConfiguration().isCertificateCheckEnabled()); + // Check if the metadatas is valid + Validator validator = new Validator(certificates, + configurationService.getConfiguration().getSamlIdpConfiguration().isCertificateCheckEnabled()); - spValidators.put(spMetadata.getEntityID(), validator); - spMetadatas.put(spMetadata.getEntityID(), spMetadata); + spValidators.put(spMetadata.getEntityID(), validator); + spMetadatas.put(spMetadata.getEntityID(), spMetadata); - HashMap fileProperties = new HashMap<>(); + HashMap fileProperties = new HashMap<>(); - fileProperties.put("issuer", spMetadata.getEntityID()); - fileProperties.put("hash", FileUtils.getFileHash(filename)); + fileProperties.put("issuer", spMetadata.getEntityID()); + fileProperties.put("hash", FileUtils.getFileHash(filename)); - loadedSpFiles.put(filename, fileProperties); - } + loadedSpFiles.put(filename, fileProperties); + } - private void unloadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, - UntrustedSignerException, InvalidSignatureException { + private void unloadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, + UntrustedSignerException, InvalidSignatureException { - LOG.info("Unloading SAML SP metadata: {}", filename); + LOG.info("Unloading SAML SP metadata: {}", filename); - HashMap fileProperties = loadedSpFiles.get(filename); + HashMap fileProperties = loadedSpFiles.get(filename); - String issuer = fileProperties.get("issuer"); + String issuer = fileProperties.get("issuer"); - spMetadatas.remove(issuer); - spValidators.remove(issuer); - } + spMetadatas.remove(issuer); + spValidators.remove(issuer); + } - private void checkUpdatedMetadata(String filename) throws NoSuchAlgorithmException, IOException, TechnicalException, - UnsignedSAMLObjectException, UntrustedSignerException, InvalidSignatureException { + private void checkUpdatedMetadata(String filename) throws NoSuchAlgorithmException, IOException, TechnicalException, + UnsignedSAMLObjectException, UntrustedSignerException, InvalidSignatureException { - LOG.debug("Check update of SAML SP metadata: {}", filename); + LOG.debug("Check update of SAML SP metadata: {}", filename); - HashMap fileProperties = loadedSpFiles.get(filename); + HashMap fileProperties = loadedSpFiles.get(filename); - String hash = fileProperties.get("hash"); + String hash = fileProperties.get("hash"); - // Check if the metadata is modified - if (!FileUtils.getFileHash(filename).equals(hash)) { - unloadMetadata(filename); - loadMetadata(filename); - } - } + // Check if the metadata is modified + if (!FileUtils.getFileHash(filename).equals(hash)) { + unloadMetadata(filename); + loadMetadata(filename); + } + } - @Scheduled(fixedDelayString = "60000") - public void refreshSpMetadatas() { + @Scheduled(fixedDelayString = "60000") + public void refreshSpMetadatas() { - LOG.debug("Refreshing SAML SP metadata..."); + LOG.debug("Refreshing SAML SP metadata..."); - IdentioConfiguration config = configurationService.getConfiguration(); + IdentioConfiguration config = configurationService.getConfiguration(); - String spMetadataDirectory = config.getSamlIdpConfiguration().getSpMetadataDirectory(); + String spMetadataDirectory = config.getSamlIdpConfiguration().getSpMetadataDirectory(); + List spFiles = new ArrayList<>(); - // Build the SP metadata - List spFiles = Arrays.asList(new File(spMetadataDirectory).listFiles()).stream() - .filter(x -> x.isFile() && x.getName().endsWith(".xml")).map(x -> x.getAbsolutePath()) - .collect(Collectors.toList()); + // Build the SP metadata + File[] files = new File(spMetadataDirectory).listFiles(); - List newFileNames = new ArrayList<>(spFiles); - newFileNames.removeAll(loadedSpFiles.keySet()); + if (files != null) { + spFiles = Stream.of(files) + .filter(x -> x.isFile() && x.getName().endsWith(".xml")).map(File::getAbsolutePath) + .collect(Collectors.toList()); + } - List removedFileNames = new ArrayList<>(loadedSpFiles.keySet()); - removedFileNames.removeAll(spFiles); + List newFileNames = new ArrayList<>(spFiles); + newFileNames.removeAll(loadedSpFiles.keySet()); - List existingFileNames = new ArrayList<>(loadedSpFiles.keySet()); - existingFileNames.retainAll(spFiles); + List removedFileNames = new ArrayList<>(loadedSpFiles.keySet()); + removedFileNames.removeAll(spFiles); - try { - for (String filename : newFileNames) { - loadMetadata(filename); - } + List existingFileNames = new ArrayList<>(loadedSpFiles.keySet()); + existingFileNames.retainAll(spFiles); - for (String filename : removedFileNames) { - unloadMetadata(filename); - } + try { + for (String filename : newFileNames) { + loadMetadata(filename); + } - for (String filename : existingFileNames) { - checkUpdatedMetadata(filename); - } + for (String filename : removedFileNames) { + unloadMetadata(filename); + } - } catch (NoSuchAlgorithmException | TechnicalException | UnsignedSAMLObjectException | UntrustedSignerException - | InvalidSignatureException | IOException e) { - LOG.error("An error occured when refreshing SP metadatas: {}", e.getMessage()); - LOG.debug("* Detailed exception:", e); - } - } + for (String filename : existingFileNames) { + checkUpdatedMetadata(filename); + } - public Validator getSpValidator(String issuer) { - return spValidators.get(issuer); - } + } catch (NoSuchAlgorithmException | TechnicalException | UnsignedSAMLObjectException | UntrustedSignerException + | InvalidSignatureException | IOException e) { + LOG.error("An error occured when refreshing SP metadatas: {}", e.getMessage()); + LOG.debug("* Detailed exception:", e); + } + } - public Metadata getIdpMetadata() { - return idpMetadata; - } + public Validator getSpValidator(String issuer) { + return spValidators.get(issuer); + } - public Metadata getSpMetadata(String issuer) { - return spMetadatas.get(issuer); - } + public Metadata getIdpMetadata() { + return idpMetadata; + } + + public Metadata getSpMetadata(String issuer) { + return spMetadatas.get(issuer); + } } \ No newline at end of file From b7183255f94f4363d53c8f127ad6b392223f5b27 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 17:34:53 +0200 Subject: [PATCH 020/104] Added OAuth integration tests --- .../tests/oauth/OauthIntegrationTests.java | 84 ++++++++++++++++++ .../default-sign-certificate.p12 | Bin 0 -> 2381 bytes .../oauth-server-config/identio-config.yml | 48 ++++++++++ .../resources/oauth-server-config/logback.xml | 23 +++++ .../oauth-server-config/oauth-clients.yml | 11 +++ .../resources/oauth-server-config/users.yml | 3 + 6 files changed, 169 insertions(+) create mode 100644 src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java create mode 100644 src/test/resources/oauth-server-config/default-sign-certificate.p12 create mode 100644 src/test/resources/oauth-server-config/identio-config.yml create mode 100644 src/test/resources/oauth-server-config/logback.xml create mode 100644 src/test/resources/oauth-server-config/oauth-clients.yml create mode 100644 src/test/resources/oauth-server-config/users.yml diff --git a/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java b/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java new file mode 100644 index 0000000..b7f9172 --- /dev/null +++ b/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java @@ -0,0 +1,84 @@ +package net.identio.server.tests.oauth; + +import net.identio.server.boot.IdentioServerApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = IdentioServerApplication.class) +@TestPropertySource(properties = {"identio.config: src/test/resources/oauth-server-config/identio-config.yml", + "identio.public.fqdn: http://localhost:443", + "logging.config: src/test/resources/oauth-server-config/logback.xml"}) +public class OauthIntegrationTests { + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate = new TestRestTemplate(); + + @Test + public void oAuthAuthorizeRequestWithoutParameters() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithoutClientId() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithoutResponseType() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithoutRedirectUri() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token&client_id=test"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/auth"), response.getHeaders().get("Location").get(0)); + } + + + private String getUrlWithPort(String url) { + + return "http://localhost:" + port + url; + + } +} diff --git a/src/test/resources/oauth-server-config/default-sign-certificate.p12 b/src/test/resources/oauth-server-config/default-sign-certificate.p12 new file mode 100644 index 0000000000000000000000000000000000000000..135833e9afbdded26abcfb1e1c0fe704c36bb4d7 GIT binary patch literal 2381 zcmV-T39|Muf(c0i0Ru3C2@eJdDuzgg_YDCD0ic2j00e>v{4jzD_%MP4uLcP!hDe6@ z4FLxRpn?OSFoFY|0s#Opf&-NX2`Yw2hW8Bt2LUh~1_~;MNQUP6I<0Z!|tLid;@~RLfzOVzz9n^lZyb_wM4251lozo9H|>Xvzv(8 zw{@9oCias(hiNiXtvw4P)-iwcR^J?j(FjI6eC-f{guH9UV+|QpE7{RskY1G@8J6s) ztVkxrkh;QS)T3eC9)n2gGQM+MUWFfLpV?O20x#AnTwW5SlYiX5w9E@kvOBm;zl8uO ze(UlvO9gl}{eNOaBXTD>m4YoC{x1VLb5L-`lMI5yNkEigsPhz3v+xK06l})7G#F*8 zH}OBYH|>QMmI~bpRLqzLD^XV(`_a2}k20HKuO*hxfePi=@{c#|Y{% zLAYb)6P8uyO@PUU+qC-!t?{`B(KMRs=Pk_64*fxLurh87LVY?f!7P2)>z{r4decDSPAnBpgBd2sEsVUD~-|#6P!W$yO zW`S$fN}ecfO|-idg&>_jSKtsSx`6%BrBMnsQG14%g_lvzYs~;g^?@Zz*n%hh*n>_t zXusrv^#9#n)-BYL1}`jo5gXoM04(nPn#?Jy>6}>!3AQ>?pl{*Rl$Y{sd+evdc6}SrrV&jkqn#87cf*c(CZc=%+gdb zt>WW0OQfH?O~L|4YUt$eLv0>YHHwGuJtQv}aS}Z_KtlI5drBTc#Wjg?&p4Ot5W#_L zpf9foME_jcih27dTwVv}Gi1J8Yii7VbqV*`+}ThF@S8m4Nb{6&1g30|S%EJ_JOTHH z_V72ZPu#=AX&vkiWjY0gHB1YOBD6&NoWc4w#N5~n(AYNa7-iuC_KxJGz~`uDGyfhi z;T?8Y9HYt`$v{SD-x`YVbWCjq^m*H|nhNS`1t)hri7@WaUA`7}T;13^mwy28yp563 zFoFd^1_>&LNQU}y#9|@5vGovjh$h@HMf%a# zWX$NnK0fuLCdCR$m=HBA`(TX9tsPX3Eie7)yCt&qLd&v2{;1$C)*k(w2Rb|TMe(1m za9^f4{&PE|-Q#G*nR#cc>r=+dC=J0{Zu0rey%_v@eEKOPJi$Q>iVtb6&_=2?0UX=) zkZ{A4Bng-dX+umhR@?R{M4xM4Si8zbKQUSvtx6Vy&)9Xgcu}SD?D`DOjkMc6C{K%X zh62)+fqR%4j^MVwC-L1hw?o=82>o;0`3`2hcW; z8k71R+v>`{2f#g!<)2SP4AaNO=86}zO7EdSu`u8Eh8J{55=t_<-H-_Q%xQ2Gz|e~4 zi_~jkv_MLwfh!KOZ$fz+eo!#(s^Eazo9xMQvU+h?L5f*-cnnnED>I?Xa*Z$GOwv^$ z<&-Sdf5k{nHnWQ4KxAQ7v3@=C)1k~IHZegXVaal_`~f!(A59%gW}oFSEqWWrwu-1? zYA8w{?%@uyLC>b&%b__J78( zXIOb$%833P1@=ilq@8FDSfrM`XUg%!fZAn(v52RD=whK<9wggGN}ANxRK`2WYGfB) zP@4P*ViUO~s_H)!IsKtB-~~R_2v_&Ag@(NX0Cl=|;550}y_jFe)&>^kJ4EqTvh%M} zk^w5XYpGwY6>Cxzz__@C3rZ1Y>Eb<)-B_W}w1_?X=SE0#M52yczr5V82PA&RgVUbn zRY{k>gTra)RiKX)78MnG7rBQ%!B(jif?9n}qgJHZLvZ94a=-^5c?wqkM06t-8CJP;z)$3NhH z)D;u)gMSCt!VV`U;euCK`rHO4B}Xw?%WBJ&cD{})K_Vk68>SIWU)j{YxH7skL__jX z7%V%ErfxZls@Gg=JOVG6ZGWYpZ_5vuU&dNxHGbHn&U&;`Lu_D>)oiz~FDkvBqFFV_ zTqP?}Iyzz61eP|!(zL4TWgtzxs`AR-BEo&&3$JnUuu@I8ap%&opm{_@*$VFj1OCd> z-$k;W0?zg3eiDU^^~o#0-UqI@phQrj_IcVBo2sQnOt{Kw9tbo2QFAo2szcD0NA~^# zH~|}7 + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/oauth-server-config/oauth-clients.yml b/src/test/resources/oauth-server-config/oauth-clients.yml new file mode 100644 index 0000000..45357dc --- /dev/null +++ b/src/test/resources/oauth-server-config/oauth-clients.yml @@ -0,0 +1,11 @@ +oAuthClients: + - name: Test Client + clientId: test + clientSecret: test + allowedScopes: + - scope.test.1 + - scope.test.2 + responseUri: + - http://test + allowedGrants: + - implicit diff --git a/src/test/resources/oauth-server-config/users.yml b/src/test/resources/oauth-server-config/users.yml new file mode 100644 index 0000000..7aae1c7 --- /dev/null +++ b/src/test/resources/oauth-server-config/users.yml @@ -0,0 +1,3 @@ +users: + - userId: johndoe + password: $2a$10$txi/CWyeIEOWcXvrIWjpVuoqBXFRteq1TTeAaW.mWZ/3BYDRByDje From d79b5d044c4d53c91678132cfd510fbb9dc1ead4 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 17:35:17 +0200 Subject: [PATCH 021/104] Fixed redirect_uri check --- .../net/identio/server/service/oauth/OAuthService.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 818f832..e7be756 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -112,7 +112,11 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re OAuthClient client = clientRepository.getOAuthClientbyId(request.getClientId()); // Verify redirectUri - checkRedirectUri(client, request.getRedirectUri()); + String redirectUri = client.getResponseUri().get(0); + + if (request.getRedirectUri() != null && checkRedirectUri(client, request.getRedirectUri())) { + redirectUri = request.getRedirectUri(); + } // Validate response type value if (!checkValidResponseTypes(request.getResponseType())) { @@ -199,13 +203,15 @@ private boolean checkValidResponseTypes(String responseType) { return true; } - private void checkRedirectUri(OAuthClient client, String redirectUri) throws InvalidRedirectUriException { + private boolean checkRedirectUri(OAuthClient client, String redirectUri) throws InvalidRedirectUriException { if (!client.getResponseUri().contains(redirectUri)) { String message = "Unknown redirectUri: " + redirectUri; LOG.error(message); throw new InvalidRedirectUriException(message); } + + return true; } private boolean checkClientAuthorization(OAuthClient client, String responseType, List requestedScopes) { From 2eece69173cea06354bfaacad82e754bc65f1865 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 27 Jul 2017 17:42:54 +0200 Subject: [PATCH 022/104] Fixed redirect_uri check --- .../java/net/identio/server/service/oauth/OAuthService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index e7be756..8a6802f 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -137,7 +137,7 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); } - result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(request.getRedirectUri()) + result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) .setProtocolType(ProtocolType.OAUTH).setRelayState(request.getState()).setRequestedScopes(scopes) .setResponseType(request.getResponseType()); From 5fa92620bb51d2fad4b99c52b8c8dd9c12ec507d Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Fri, 28 Jul 2017 16:14:23 +0200 Subject: [PATCH 023/104] Finished initial oauth request validation and associated testing --- .../model/AuthRequestValidationResult.java | 16 +- .../net/identio/server/model/ErrorStatus.java | 3 +- .../java/net/identio/server/model/State.java | 2 +- .../GlobalControllerExceptionHandler.java | 2 +- .../server/mvc/oauth/OAuthController.java | 22 +- .../service/oauth/OAuthClientRepository.java | 3 +- .../server/service/oauth/OAuthService.java | 294 ++++++++++-------- .../exceptions/ClientNotFoundException.java | 14 - .../InvalidRedirectUriException.java | 14 - .../FileOAuthClientRepository.java | 5 +- .../service/oauth/model/OAuthErrors.java | 10 + .../server/service/saml/SamlService.java | 53 +--- .../service/validation/ValidationService.java | 19 +- .../tests/oauth/OauthIntegrationTests.java | 98 +++++- .../oauth-server-config/oauth-clients.yml | 2 +- 15 files changed, 308 insertions(+), 249 deletions(-) delete mode 100644 src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java delete mode 100644 src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java create mode 100644 src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java diff --git a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java b/src/main/java/net/identio/server/model/AuthRequestValidationResult.java index 0523839..00e3676 100644 --- a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java +++ b/src/main/java/net/identio/server/model/AuthRequestValidationResult.java @@ -24,7 +24,7 @@ License, or (at your option) any later version. public class AuthRequestValidationResult { private boolean success; - private ErrorStatus errorStatus; + private String errorStatus; private String requestId; private ProtocolType protocolType; private String sourceApplicationName; @@ -40,17 +40,17 @@ public boolean isSuccess() { return success; } - public ErrorStatus getErrorStatus() { - return errorStatus; + public AuthRequestValidationResult setSuccess(boolean success) { + this.success = success; + return this; } - public AuthRequestValidationResult setErrorStatus(ErrorStatus errorStatus) { - this.errorStatus = errorStatus; - return this; + public String getErrorStatus() { + return errorStatus; } - public AuthRequestValidationResult setSuccess(boolean success) { - this.success = success; + public AuthRequestValidationResult setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; return this; } diff --git a/src/main/java/net/identio/server/model/ErrorStatus.java b/src/main/java/net/identio/server/model/ErrorStatus.java index 674a9ad..9987ab4 100644 --- a/src/main/java/net/identio/server/model/ErrorStatus.java +++ b/src/main/java/net/identio/server/model/ErrorStatus.java @@ -20,6 +20,5 @@ License, or (at your option) any later version. package net.identio.server.model; public enum ErrorStatus { - OAUTH_RESPONSE_TYPE_NOT_SUPPORTED, OAUTH_CLIENT_NOT_FOUND, OAUTH_UNAUTHORIZED_CLIENT, OAUTH_INVALID_SCOPE, - AUTH_USER_ID_MISMATCH, AUTH_SAML_WRONG_AUDIENCE, AUTH_SAML_NO_RECIPIENT, AUTH_SAML_NO_DESTINATION, AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION, AUTH_SAML_CONDITIONS_NOT_MET, AUTH_SAML_INVALID_RESPONSE, AUTH_SAML_REJECTED_BY_PROXY, AUTH_SAML_NO_ASSERTION_IN_RESPONSE, AUTH_SAML_INVALID_INRESPONSETO, AUTH_USER_NOT_UNIQUE, AUTH_INVALID_CREDENTIALS, AUTH_TECHNICAL_ERROR, BUILD_AUTHENT_REQUEST_FAILED, AUTH_LEVEL_UNKNOWN, AUTH_NO_CREDENTIALS, AUTH_METHOD_UNKNOWN, AUTH_METHOD_NOT_ALLOWED, AUTHENT_REQUEST_ISSUER_UNKNOWN, AUTHENT_REQUEST_ISSUER_EMPTY, AUTHENT_REQUEST_NO_DESTINATION, AUTHENT_REQUEST_UNKNOWN_ENDPOINT, AUTHENT_REQUEST_INVALID_ENCODING, AUTHENT_REQUEST_NOT_SIGNED, AUTHENT_REQUEST_SIGNATURE_INVALID + AUTH_USER_ID_MISMATCH, AUTH_SAML_WRONG_AUDIENCE, AUTH_SAML_NO_RECIPIENT, AUTH_SAML_NO_DESTINATION, AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION, AUTH_SAML_CONDITIONS_NOT_MET, AUTH_SAML_INVALID_RESPONSE, AUTH_SAML_REJECTED_BY_PROXY, AUTH_SAML_NO_ASSERTION_IN_RESPONSE, AUTH_SAML_INVALID_INRESPONSETO, AUTH_USER_NOT_UNIQUE, AUTH_INVALID_CREDENTIALS, AUTH_TECHNICAL_ERROR, AUTH_NO_CREDENTIALS, AUTH_METHOD_UNKNOWN, AUTH_METHOD_NOT_ALLOWED } diff --git a/src/main/java/net/identio/server/model/State.java b/src/main/java/net/identio/server/model/State.java index bcc7939..0448d9e 100644 --- a/src/main/java/net/identio/server/model/State.java +++ b/src/main/java/net/identio/server/model/State.java @@ -20,5 +20,5 @@ License, or (at your option) any later version. package net.identio.server.model; public enum State { - AUTH, STEP_UP_AUTHENTICATION, RESPONSE, CONSENT + AUTH, STEP_UP_AUTHENTICATION, RESPONSE, CONSENT, ERROR } diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index cfa6edf..3e0ecb2 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -47,6 +47,6 @@ public String handleValidationException() { @ExceptionHandler(ServletRequestBindingException.class) public String handleServletRequestBindingException() { - return errorController.displayErrorPage("error.missing.parameter"); + return errorController.displayErrorPage("missing.parameter"); } } diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index 21c1dc0..65ea4c3 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -53,8 +53,8 @@ public class OAuthController { private PreAuthController preAuthController; @RequestMapping(value = "/oauth/authorize", method = RequestMethod.GET) - public String authorizeRequest(@RequestParam("response_type") String responseType, - @RequestParam("client_id") String clientId, + public String authorizeRequest(@RequestParam(value = "response_type", required = false) String responseType, + @RequestParam(value = "client_id", required = false) String clientId, @RequestParam(value = "redirect_uri", required = false) String redirectUri, @RequestParam(value = "scope", required = false) String scopes, @RequestParam(value = "state", required = false) String state, @@ -76,14 +76,16 @@ public String authorizeRequest(@RequestParam("response_type") String responseTyp ValidationResult result = validationService.validateAuthentRequest(request, identioSession); switch (result.getState()) { - case RESPONSE: - return "redirect:" + result.getResponseData(); - - case CONSENT: - return "redirect:/#/consent/"; - - default: - return preAuthController.checkTransparentAuthentication(httpRequest, httpResponse, result); + case RESPONSE: + return "redirect:" + result.getResponseData(); + + case CONSENT: + return "redirect:/#!/consent/"; + + case ERROR: + return "redirect:/#!/error/" + result.getArValidationResult().getErrorStatus(); + default: + return preAuthController.checkTransparentAuthentication(httpRequest, httpResponse, result); } } diff --git a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java index 8d55028..5c7d660 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java @@ -1,10 +1,9 @@ package net.identio.server.service.oauth; import net.identio.server.model.OAuthClient; -import net.identio.server.service.oauth.exceptions.ClientNotFoundException; public interface OAuthClientRepository { - OAuthClient getOAuthClientbyId(String cliendId) throws ClientNotFoundException; + OAuthClient getOAuthClientbyId(String cliendId); } diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 8a6802f..bee53b8 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -31,6 +31,7 @@ License, or (at your option) any later version. import java.util.List; import java.util.UUID; +import net.identio.server.service.oauth.model.OAuthErrors; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.slf4j.Logger; @@ -43,7 +44,6 @@ License, or (at your option) any later version. import net.identio.server.exceptions.InitializationException; import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.ErrorStatus; import net.identio.server.model.OAuthClient; import net.identio.server.model.OAuthInboundRequest; import net.identio.server.model.ProtocolType; @@ -53,185 +53,207 @@ License, or (at your option) any later version. import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; import net.identio.server.service.authorization.exceptions.UnknownScopeException; import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.oauth.exceptions.ClientNotFoundException; -import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; import net.identio.server.service.oauth.model.OAuthGrants; import net.identio.server.service.oauth.model.OAuthResponseType; @Service public class OAuthService { - private static final Logger LOG = LoggerFactory.getLogger(OAuthService.class); + private static final Logger LOG = LoggerFactory.getLogger(OAuthService.class); - @Autowired - private OAuthClientRepository clientRepository; - @Autowired - private AuthorizationService authorizationService; + @Autowired + private OAuthClientRepository clientRepository; + @Autowired + private AuthorizationService authorizationService; - private ConfigurationService configurationService; + private ConfigurationService configurationService; - private RSAKey signingKey; + private RSAKey signingKey; - @Autowired - public OAuthService(ConfigurationService configurationService) throws InitializationException { - this.configurationService = configurationService; + @Autowired + public OAuthService(ConfigurationService configurationService) throws InitializationException { + this.configurationService = configurationService; - // Cache signing certificate - try (FileInputStream fis = new FileInputStream( - configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePath())) { - KeyStore ks = KeyStore.getInstance("PKCS12"); - ks.load(fis, configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePassword() - .toCharArray()); + // Cache signing certificate + try (FileInputStream fis = new FileInputStream( + configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePath())) { + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(fis, configurationService.getConfiguration().getGlobalConfiguration().getSignatureKeystorePassword() + .toCharArray()); - Enumeration aliases = ks.aliases(); + Enumeration aliases = ks.aliases(); - if (aliases == null || !aliases.hasMoreElements()) { - throw new InitializationException("Keystore doesn't contain a certificate"); - } + if (aliases == null || !aliases.hasMoreElements()) { + throw new InitializationException("Keystore doesn't contain a certificate"); + } - String alias = aliases.nextElement(); + String alias = aliases.nextElement(); - KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, - new KeyStore.PasswordProtection(configurationService.getConfiguration().getGlobalConfiguration() - .getSignatureKeystorePassword().toCharArray())); + KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry) ks.getEntry(alias, + new KeyStore.PasswordProtection(configurationService.getConfiguration().getGlobalConfiguration() + .getSignatureKeystorePassword().toCharArray())); - signingKey = (RSAKey) keyEntry.getPrivateKey(); + signingKey = (RSAKey) keyEntry.getPrivateKey(); - } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException - | UnrecoverableEntryException ex) { - throw new InitializationException("Could not initialize OAuth Service", ex); - } - } + } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException + | UnrecoverableEntryException ex) { + throw new InitializationException("Could not initialize OAuth Service", ex); + } + } - public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) - throws ClientNotFoundException, InvalidRedirectUriException { + public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) { - AuthRequestValidationResult result = new AuthRequestValidationResult(); + AuthRequestValidationResult result = new AuthRequestValidationResult(); - // Fetch client - OAuthClient client = clientRepository.getOAuthClientbyId(request.getClientId()); + result.setProtocolType(ProtocolType.OAUTH); - // Verify redirectUri - String redirectUri = client.getResponseUri().get(0); + // Handle state and copy it in the response + if (request.getState() != null) { + result.setRelayState(request.getState()); + } - if (request.getRedirectUri() != null && checkRedirectUri(client, request.getRedirectUri())) { - redirectUri = request.getRedirectUri(); - } + // Fetch client + OAuthClient client = clientRepository.getOAuthClientbyId(request.getClientId()); + if (client == null) { + return result.setSuccess(false).setErrorStatus(OAuthErrors.UNKNOWN_CLIENT); + } - // Validate response type value - if (!checkValidResponseTypes(request.getResponseType())) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_RESPONSE_TYPE_NOT_SUPPORTED); - } + // Verify redirectUri + String redirectUri = client.getResponseUri().get(0); - // Validate scope value - List scopes; - try { - scopes = authorizationService.getScopes(request.getScopes()); - } catch (UnknownScopeException | NoScopeProvidedException e) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_INVALID_SCOPE); - } + if (request.getRedirectUri() != null) { + if (checkRedirectUri(client, request.getRedirectUri())) { + redirectUri = request.getRedirectUri(); + } else { + return result.setSuccess(false).setErrorStatus(OAuthErrors.UNKNOWN_REDIRECT_URI); + } + } - // Validate client authorization regarding allowed scopes and response - // types - if (!checkClientAuthorization(client, request.getResponseType(), request.getScopes())) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.OAUTH_UNAUTHORIZED_CLIENT); - } + // Validate response type value + if (request.getResponseType() == null || !checkValidResponseTypes(request.getResponseType())) { + return result.setSuccess(false).setErrorStatus(OAuthErrors.RESPONSE_TYPE_NOT_SUPPORTED) + .setResponseUrl(redirectUri); + } - result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) - .setProtocolType(ProtocolType.OAUTH).setRelayState(request.getState()).setRequestedScopes(scopes) - .setResponseType(request.getResponseType()); + // Validate scope value + List scopes; + try { + scopes = authorizationService.getScopes(request.getScopes()); + } catch (UnknownScopeException | NoScopeProvidedException e) { + return result.setSuccess(false).setErrorStatus(OAuthErrors.INVALID_SCOPE).setResponseUrl(redirectUri); + } - return result; - } + // Validate client authorization regarding allowed scopes and response + // types + if (!checkClientAuthorization(client, request.getResponseType(), request.getScopes())) { + return result.setSuccess(false).setErrorStatus(OAuthErrors.UNAUTHORIZED_CLIENT).setResponseUrl(redirectUri); + } - public String generateSuccessResponse(AuthRequestValidationResult result, UserSession userSession) { + result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) + .setRequestedScopes(scopes).setResponseType(request.getResponseType()); - // http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600 - StringBuilder responseBuilder = new StringBuilder(); + return result; + } - responseBuilder.append(result.getResponseUrl()).append("#"); + public String generateSuccessResponse(AuthRequestValidationResult result, UserSession userSession) { - // Determine expiration time of the authorization - int expirationTime = -1; - for (AuthorizationScope scope : result.getRequestedScopes()) { - if (expirationTime == -1 || scope.getExpirationTime() < expirationTime) { - expirationTime = scope.getExpirationTime(); - } - } - - responseBuilder.append("expires_in=").append(expirationTime); - - // Calculate scope string - StringBuilder scopeBuilder = new StringBuilder(); - for (AuthorizationScope scope : result.getRequestedScopes()) { - scopeBuilder.append(scope.getName()).append(' '); - } + // http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600 + StringBuilder responseBuilder = new StringBuilder(); - scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma + responseBuilder.append(result.getResponseUrl()).append("#"); - if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { - responseBuilder.append("&token_type=Bearer"); - - DateTime now = new DateTime(DateTimeZone.UTC); + // Determine expiration time of the authorization + int expirationTime = -1; + for (AuthorizationScope scope : result.getRequestedScopes()) { + if (expirationTime == -1 || scope.getExpirationTime() < expirationTime) { + expirationTime = scope.getExpirationTime(); + } + } - String accessToken = JWT.create().withIssuer(configurationService.getPublicFqdn()) - .withExpiresAt(now.plusSeconds(expirationTime).toDate()).withIssuedAt(now.toDate()) - .withSubject(userSession.getUserId()).withAudience(result.getSourceApplicationName()) - .withJWTId(UUID.randomUUID().toString()).withClaim("scope", scopeBuilder.toString()) - .sign(Algorithm.RSA256(signingKey)); + responseBuilder.append("expires_in=").append(expirationTime); - responseBuilder.append("&access_token=").append(accessToken); - } + // Calculate scope string + StringBuilder scopeBuilder = new StringBuilder(); + for (AuthorizationScope scope : result.getRequestedScopes()) { + scopeBuilder.append(scope.getName()).append(' '); + } - if (result.getRelayState() != null) { - responseBuilder.append("&state=").append(result.getRelayState()); - } + scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma - System.out.println(responseBuilder.toString()); - - return responseBuilder.toString(); - } + if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { + responseBuilder.append("&token_type=Bearer"); - private boolean checkValidResponseTypes(String responseType) { + DateTime now = new DateTime(DateTimeZone.UTC); - // Only valid response types are "token" and "code" - if (!responseType.equals(OAuthResponseType.CODE) && !responseType.equals(OAuthResponseType.TOKEN)) { - LOG.error("ResponseType not supported: {}", responseType); - return false; - } + String accessToken = JWT.create().withIssuer(configurationService.getPublicFqdn()) + .withExpiresAt(now.plusSeconds(expirationTime).toDate()).withIssuedAt(now.toDate()) + .withSubject(userSession.getUserId()).withAudience(result.getSourceApplicationName()) + .withJWTId(UUID.randomUUID().toString()).withClaim("scope", scopeBuilder.toString()) + .sign(Algorithm.RSA256(signingKey)); - return true; - } + responseBuilder.append("&access_token=").append(accessToken); + } - private boolean checkRedirectUri(OAuthClient client, String redirectUri) throws InvalidRedirectUriException { + if (result.getRelayState() != null) { + responseBuilder.append("&state=").append(result.getRelayState()); + } - if (!client.getResponseUri().contains(redirectUri)) { - String message = "Unknown redirectUri: " + redirectUri; - LOG.error(message); - throw new InvalidRedirectUriException(message); - } + return responseBuilder.toString(); + } - return true; - } - - private boolean checkClientAuthorization(OAuthClient client, String responseType, List requestedScopes) { - - if (!responseType.equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains(OAuthGrants.IMPLICIT) - || !responseType.equals(OAuthResponseType.CODE) - && client.getAllowedGrants().contains(OAuthGrants.AUTHORIZATION_CODE)) { - - LOG.error("Client not authorized to use the response type: {}", responseType); - return false; - } - - if (!client.getAllowedScopes().containsAll(requestedScopes)) { - - LOG.error("Client not authorized to use the requested scope"); - return false; - } + public String generateErrorResponse(AuthRequestValidationResult result) { - return true; + StringBuilder responseBuilder = new StringBuilder(); - } + responseBuilder.append(result.getResponseUrl()).append("#error=").append(result.getErrorStatus()); + + if (result.getRelayState() != null) { + responseBuilder.append("&state=").append(result.getRelayState()); + } + + return responseBuilder.toString(); + } + + private boolean checkValidResponseTypes(String responseType) { + + // Only valid response types are "token" and "code" + if (!responseType.equals(OAuthResponseType.CODE) && !responseType.equals(OAuthResponseType.TOKEN)) { + LOG.error("ResponseType not supported: {}", responseType); + return false; + } + + return true; + } + + private boolean checkRedirectUri(OAuthClient client, String redirectUri) { + + if (!client.getResponseUri().contains(redirectUri)) { + String message = "Unknown redirectUri: " + redirectUri; + LOG.error(message); + return false; + } + + return true; + } + + private boolean checkClientAuthorization(OAuthClient client, String responseType, List requestedScopes) { + + if (!responseType.equals(OAuthResponseType.TOKEN) && client.getAllowedGrants().contains(OAuthGrants.IMPLICIT) + || !responseType.equals(OAuthResponseType.CODE) + && client.getAllowedGrants().contains(OAuthGrants.AUTHORIZATION_CODE)) { + + LOG.error("Client not authorized to use the response type: {}", responseType); + return false; + } + + if (!client.getAllowedScopes().containsAll(requestedScopes)) { + + LOG.error("Client not authorized to use the requested scope"); + return false; + } + + return true; + + } } diff --git a/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java b/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java deleted file mode 100644 index 9fbedb2..0000000 --- a/src/main/java/net/identio/server/service/oauth/exceptions/ClientNotFoundException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.identio.server.service.oauth.exceptions; - -public class ClientNotFoundException extends Exception { - - private static final long serialVersionUID = -3334461077718669313L; - - public ClientNotFoundException(String s) { - super(s); - } - - public ClientNotFoundException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java b/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java deleted file mode 100644 index ad7704b..0000000 --- a/src/main/java/net/identio/server/service/oauth/exceptions/InvalidRedirectUriException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.identio.server.service.oauth.exceptions; - -public class InvalidRedirectUriException extends Exception { - - private static final long serialVersionUID = -3334461077718669313L; - - public InvalidRedirectUriException(String s) { - super(s); - } - - public InvalidRedirectUriException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java index 432a32d..81a95a2 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -16,7 +16,6 @@ import net.identio.server.model.OAuthClient; import net.identio.server.service.configuration.ConfigurationService; import net.identio.server.service.oauth.OAuthClientRepository; -import net.identio.server.service.oauth.exceptions.ClientNotFoundException; @Service public class FileOAuthClientRepository implements OAuthClientRepository { @@ -61,9 +60,7 @@ public FileOAuthClientRepository(ConfigurationService configurationService) thro } @Override - public OAuthClient getOAuthClientbyId(String cliendId) throws ClientNotFoundException { - - if (!clients.containsKey(cliendId)) { throw new ClientNotFoundException("Unknown clientId"); } + public OAuthClient getOAuthClientbyId(String cliendId) { return clients.get(cliendId); } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java new file mode 100644 index 0000000..0236981 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java @@ -0,0 +1,10 @@ +package net.identio.server.service.oauth.model; + +public class OAuthErrors { + + public static final String UNKNOWN_CLIENT = "unknown.client"; + public static final String UNKNOWN_REDIRECT_URI = "unknown.redirect.uri"; + public static final String RESPONSE_TYPE_NOT_SUPPORTED = "unsupported_response_type"; + public static final String INVALID_SCOPE = "invalid_scope"; + public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; +} diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index a6ae346..5609af2 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -22,7 +22,6 @@ License, or (at your option) any later version. import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.HashMap; import java.util.zip.DataFormatException; import org.apache.xml.security.exceptions.Base64DecodingException; @@ -59,7 +58,6 @@ License, or (at your option) any later version. import net.identio.server.model.AuthPolicyDecision; import net.identio.server.model.AuthRequestValidationResult; import net.identio.server.model.AuthSession; -import net.identio.server.model.ErrorStatus; import net.identio.server.model.IdentioConfiguration; import net.identio.server.model.ProtocolType; import net.identio.server.model.SamlAuthRequestGenerationResult; @@ -83,8 +81,6 @@ public class SamlService { private AuthPolicyService authPolicyService; - private HashMap errorMapping; - @Autowired public SamlService(ConfigurationService configurationService, MetadataService metadataService, AuthPolicyService authPolicyService) throws InitializationException { @@ -93,8 +89,6 @@ public SamlService(ConfigurationService configurationService, MetadataService me this.metadataService = metadataService; this.authPolicyService = authPolicyService; - initErrorMapping(); - try { initSigner(configurationService.getConfiguration()); @@ -117,21 +111,6 @@ private void initSigner(IdentioConfiguration config) throws TechnicalException { SamlConstants.SIGNATURE_ALG_RSA_SHA256); } - private void initErrorMapping() { - - errorMapping = new HashMap<>(); - - errorMapping.put(ErrorStatus.BUILD_AUTHENT_REQUEST_FAILED, SamlConstants.STATUS_REQUEST_UNSUPPORTED); - errorMapping.put(ErrorStatus.AUTH_LEVEL_UNKNOWN, SamlConstants.STATUS_NO_AUTHN_CONTEXT); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_ISSUER_EMPTY, SamlConstants.STATUS_REQUEST_DENIED); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_ISSUER_UNKNOWN, SamlConstants.STATUS_REQUEST_DENIED); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_NO_DESTINATION, SamlConstants.STATUS_UNSUPPORTED_BINDING); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_UNKNOWN_ENDPOINT, SamlConstants.STATUS_UNSUPPORTED_BINDING); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_INVALID_ENCODING, SamlConstants.STATUS_REQUEST_UNSUPPORTED); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_SIGNATURE_INVALID, SamlConstants.STATUS_REQUEST_DENIED); - errorMapping.put(ErrorStatus.AUTHENT_REQUEST_NOT_SIGNED, SamlConstants.STATUS_REQUEST_DENIED); - } - public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest request) { LOG.debug("Starting SAML Authentication Request validation..."); @@ -141,13 +120,12 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req result.setProtocolType(ProtocolType.SAML); // Parse the authentication request - AuthentRequest ar = null; - + AuthentRequest ar; try { ar = AuthentRequestBuilder.getInstance().build(request.getSerializedRequest(), false); } catch (TechnicalException | InvalidRequestException e1) { LOG.error("Impossible to build AuthentRequest"); - return result.setSuccess(false).setErrorStatus(ErrorStatus.BUILD_AUTHENT_REQUEST_FAILED); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); } // Extract interesting values @@ -161,7 +139,7 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req if (destinationEndpoint == null) { LOG.error("No suitable response endpoint found"); - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_UNKNOWN_ENDPOINT); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) @@ -176,7 +154,7 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req try { requestedAuthLevels.add(authPolicyService.getAuthLevelByUrn(authLevelString)); } catch (UnknownAuthLevelException e) { - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTH_LEVEL_UNKNOWN); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_NO_AUTHN_CONTEXT); } } @@ -196,14 +174,14 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req // The request issuer field cannot be null if (requestIssuer == null) { LOG.error("Request Issuer is empty"); - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_ISSUER_EMPTY); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); } // Check if the issuer is registered Validator validator = metadataService.getSpValidator(requestIssuer); if (validator == null) { LOG.error("No validator found for issuer {}", requestIssuer); - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_ISSUER_UNKNOWN); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); } // Check that we are the recipient of the Authentication Request @@ -211,7 +189,7 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req if (destination == null) { LOG.error("No destination specified in request"); - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_NO_DESTINATION); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } else { @@ -227,7 +205,7 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req } if (!endpointFound) { LOG.error("The request destination doesn't match server SAML endpoints"); - return result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_UNKNOWN_ENDPOINT); + return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } } @@ -254,7 +232,7 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest try { signature = DecodeUtils.decode(request.getSignatureValue(), false); } catch (Base64DecodingException | IOException | DataFormatException e) { - result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_INVALID_ENCODING); + result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); return false; } String signedInfo = request.getSignedInfo(); @@ -268,7 +246,7 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest validator.validate(signedInfo, signature, sigAlg); } catch (NoSuchAlgorithmException | TechnicalException | InvalidSignatureException e) { LOG.error("Request signature is invalid"); - result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_SIGNATURE_INVALID); + result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -280,7 +258,7 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { LOG.error("Unsigned requests are not supported."); - result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_NOT_SIGNED); + result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } } @@ -301,7 +279,7 @@ private boolean validatePostRequest(Validator validator, AuthentRequest ar, Auth } catch (NoSuchAlgorithmException | UnsignedSAMLObjectException | TechnicalException | UntrustedSignerException | InvalidSignatureException e) { LOG.error("Request signature is invalid"); - result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_SIGNATURE_INVALID); + result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -312,7 +290,7 @@ private boolean validatePostRequest(Validator validator, AuthentRequest ar, Auth if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { LOG.error("Unsigned requests are not supported."); - result.setSuccess(false).setErrorStatus(ErrorStatus.AUTHENT_REQUEST_NOT_SIGNED); + result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -395,7 +373,7 @@ public String generateErrorResponse(AuthRequestValidationResult result) throws S // Build the response AuthentResponse response = AuthentResponseBuilder.getInstance() .setIssuer(metadataService.getIdpMetadata().getEntityID()) - .setStatus(false, errorMapping.get(result.getErrorStatus())).setDestination(destinationUrl).build(); + .setStatus(false, result.getErrorStatus()).setDestination(destinationUrl).build(); LOG.debug("* SAML response built"); @@ -429,9 +407,6 @@ private Endpoint findResponseEndpoint(AuthentRequest ar) { break outerloop; } } else { - if (endpoint == null) { - selectedEndpoint = endpoint; - } if (endpoint.isDefault()) { selectedEndpoint = endpoint; } diff --git a/src/main/java/net/identio/server/service/validation/ValidationService.java b/src/main/java/net/identio/server/service/validation/ValidationService.java index aad04b5..cbbd802 100644 --- a/src/main/java/net/identio/server/service/validation/ValidationService.java +++ b/src/main/java/net/identio/server/service/validation/ValidationService.java @@ -57,8 +57,6 @@ License, or (at your option) any later version. import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; import net.identio.server.service.authpolicy.AuthPolicyService; import net.identio.server.service.oauth.OAuthService; -import net.identio.server.service.oauth.exceptions.ClientNotFoundException; -import net.identio.server.service.oauth.exceptions.InvalidRedirectUriException; import net.identio.server.service.saml.SamlService; import net.identio.server.service.transaction.TransactionService; import net.identio.server.service.usersession.UserSessionService; @@ -102,19 +100,20 @@ public ValidationResult validateAuthentRequest(InboundRequest request, String se arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest) request); } if (request instanceof OAuthInboundRequest) { - try { - arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest) request); - } catch (ClientNotFoundException | InvalidRedirectUriException e) { - throw new ValidationException("An error occured when processing the request", e); - } + arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest) request); } validationResult.setArValidationResult(arValidationResult); if (!arValidationResult.isSuccess()) { - validationResult.setState(State.RESPONSE); - validationResult.setResponseData(generateFatalErrorResponse(arValidationResult)); + if (arValidationResult.getResponseUrl() != null) { + validationResult.setState(State.RESPONSE); + validationResult.setResponseData(generateFatalErrorResponse(arValidationResult)); + } + else { + validationResult.setState(State.ERROR); + } return validationResult; } @@ -375,7 +374,7 @@ private String generateFatalErrorResponse(AuthRequestValidationResult arValidati throw new ValidationException(message, e); } } else { - throw new UnsupportedOperationException(); + return oauthService.generateErrorResponse(arValidationResult); } } diff --git a/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java b/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java index b7f9172..a81ec96 100644 --- a/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java +++ b/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java @@ -12,6 +12,7 @@ import org.springframework.test.context.junit4.SpringRunner; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, @@ -36,45 +37,128 @@ public void oAuthAuthorizeRequestWithoutParameters() { String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); } @Test public void oAuthAuthorizeRequestWithoutClientId() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token"), + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithInvalidClientId() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=invalid&response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); } @Test public void oAuthAuthorizeRequestWithoutResponseType() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test"), + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/error.missing.parameter"), response.getHeaders().get("Location").get(0)); + assertEquals("http://example.com/cb#error=unsupported_response_type&state=1234", response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithInvalidResponseType() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=invalid&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals("http://example.com/cb#error=unsupported_response_type&state=1234", response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithUnauthorizedResponseType() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=code&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals("http://example.com/cb#error=unauthorized_client&state=1234", response.getHeaders().get("Location").get(0)); } @Test public void oAuthAuthorizeRequestWithoutRedirectUri() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token&client_id=test"), + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=token&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertTrue(response.getHeaders().get("Location").get(0).startsWith(getUrlWithPort("/#!/auth/"))); + } + + @Test + public void oAuthAuthorizeRequestWithUnknownUri() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://evil.com/cb&response_type=token&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals(getUrlWithPort("/#!/error/unknown.redirect.uri"), response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeRequestWithoutScope() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/auth"), response.getHeaders().get("Location").get(0)); + assertEquals("http://example.com/cb#error=invalid_scope&state=1234", response.getHeaders().get("Location").get(0)); } + @Test + public void oAuthAuthorizeRequestWithInvalidScope() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&scope=invalid&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertEquals("http://example.com/cb#error=invalid_scope&state=1234", response.getHeaders().get("Location").get(0)); + } + + @Test + public void oAuthAuthorizeValidRequest() { + + ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&response_type=token&scope=scope.test.1&state=1234"), + HttpMethod.GET, + new HttpEntity(null, new HttpHeaders()), + String.class); + + assertEquals(HttpStatus.FOUND, response.getStatusCode()); + assertTrue(response.getHeaders().get("Location").get(0).startsWith(getUrlWithPort("/#!/auth/"))); + } private String getUrlWithPort(String url) { diff --git a/src/test/resources/oauth-server-config/oauth-clients.yml b/src/test/resources/oauth-server-config/oauth-clients.yml index 45357dc..f75c474 100644 --- a/src/test/resources/oauth-server-config/oauth-clients.yml +++ b/src/test/resources/oauth-server-config/oauth-clients.yml @@ -6,6 +6,6 @@ oAuthClients: - scope.test.1 - scope.test.2 responseUri: - - http://test + - http://example.com/cb allowedGrants: - implicit From c9fd062dc5f1a9e1dcb025f1e44a674ada0d0f09 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Wed, 9 Aug 2017 00:07:42 +0200 Subject: [PATCH 024/104] Fixed oauth token expiration time computation and added a default value of 3600 seconds --- .../net/identio/server/service/oauth/OAuthService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index bee53b8..57c8920 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -165,8 +165,11 @@ public String generateSuccessResponse(AuthRequestValidationResult result, UserSe // Determine expiration time of the authorization int expirationTime = -1; for (AuthorizationScope scope : result.getRequestedScopes()) { - if (expirationTime == -1 || scope.getExpirationTime() < expirationTime) { - expirationTime = scope.getExpirationTime(); + + int scopeExpirationTime = scope.getExpirationTime() != 0 ? scope.getExpirationTime() : 3600; + + if (expirationTime == -1 || scopeExpirationTime < expirationTime) { + expirationTime = scopeExpirationTime; } } From c29b07ecdb11b9fc2d74c4e33443294742f7d898 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Wed, 9 Aug 2017 00:09:04 +0200 Subject: [PATCH 025/104] Added a successful complete cinematic for Implicit OAuth Code cleanup of integration tests --- .../oauth/InitialRequestTests.java} | 74 ++++++------ .../oauth/OAuthImplicitFullCinematicTest.java | 114 ++++++++++++++++++ .../oauth-server-config/identio-config.yml | 2 + 3 files changed, 156 insertions(+), 34 deletions(-) rename src/test/java/net/identio/server/tests/{oauth/OauthIntegrationTests.java => integ/oauth/InitialRequestTests.java} (59%) create mode 100644 src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java diff --git a/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java b/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java similarity index 59% rename from src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java rename to src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java index a81ec96..184756c 100644 --- a/src/test/java/net/identio/server/tests/oauth/OauthIntegrationTests.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java @@ -1,4 +1,4 @@ -package net.identio.server.tests.oauth; +package net.identio.server.tests.integ.oauth; import net.identio.server.boot.IdentioServerApplication; import org.junit.Test; @@ -20,7 +20,7 @@ @TestPropertySource(properties = {"identio.config: src/test/resources/oauth-server-config/identio-config.yml", "identio.public.fqdn: http://localhost:443", "logging.config: src/test/resources/oauth-server-config/logback.xml"}) -public class OauthIntegrationTests { +public class InitialRequestTests { @LocalServerPort private int port; @@ -28,136 +28,142 @@ public class OauthIntegrationTests { @Autowired private TestRestTemplate restTemplate = new TestRestTemplate(); + private static final String AUTHORIZE_URL = "/oauth/authorize"; + private static final String AUTHENTICATION_URL = "/#!/auth/"; + private static final String UNKNOWN_CLIENT_ERROR_URL = "/#!/error/unknown.client"; + private static final String UNSUPPORTED_RESPONSE_TYPE_ERROR_URL = "http://example.com/cb#error=unsupported_response_type&state=1234"; + private static final String UNAUTHORIZED_CLIENT_ERROR_URL = "http://example.com/cb#error=unauthorized_client&state=1234"; + private static final String UNKNOWN_REDIRECT_URI_ERROR_URL = "/#!/error/unknown.redirect.uri"; + private static final String INVALID_SCOPE_ERROR_URI = "http://example.com/cb#error=invalid_scope&state=1234"; + @Test public void oAuthAuthorizeRequestWithoutParameters() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort(AUTHORIZE_URL), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort(UNKNOWN_CLIENT_ERROR_URL), response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithoutClientId() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort(UNKNOWN_CLIENT_ERROR_URL), response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithInvalidClientId() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=invalid&response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=invalid&response_type=token&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/unknown.client"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort(UNKNOWN_CLIENT_ERROR_URL), response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithoutResponseType() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals("http://example.com/cb#error=unsupported_response_type&state=1234", response.getHeaders().get("Location").get(0)); + assertEquals(UNSUPPORTED_RESPONSE_TYPE_ERROR_URL, response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithInvalidResponseType() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=invalid&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&response_type=invalid&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals("http://example.com/cb#error=unsupported_response_type&state=1234", response.getHeaders().get("Location").get(0)); + assertEquals(UNSUPPORTED_RESPONSE_TYPE_ERROR_URL, response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithUnauthorizedResponseType() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=code&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&response_type=code&redirect_uri=http://example.com/cb&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals("http://example.com/cb#error=unauthorized_client&state=1234", response.getHeaders().get("Location").get(0)); + assertEquals(UNAUTHORIZED_CLIENT_ERROR_URL, response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithoutRedirectUri() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&response_type=token&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&response_type=token&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertTrue(response.getHeaders().get("Location").get(0).startsWith(getUrlWithPort("/#!/auth/"))); + assertTrue(response.getHeaders().getFirst(HttpHeaders.LOCATION).startsWith(getUrlWithPort(AUTHENTICATION_URL))); } @Test public void oAuthAuthorizeRequestWithUnknownUri() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://evil.com/cb&response_type=token&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://evil.com/cb&response_type=token&scope=scope.test.1&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals(getUrlWithPort("/#!/error/unknown.redirect.uri"), response.getHeaders().get("Location").get(0)); + assertEquals(getUrlWithPort(UNKNOWN_REDIRECT_URI_ERROR_URL), response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithoutScope() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals("http://example.com/cb#error=invalid_scope&state=1234", response.getHeaders().get("Location").get(0)); + assertEquals(INVALID_SCOPE_ERROR_URI, response.getHeaders().getFirst(HttpHeaders.LOCATION)); } @Test public void oAuthAuthorizeRequestWithInvalidScope() { - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&scope=invalid&state=1234"), - HttpMethod.GET, - new HttpEntity(null, new HttpHeaders()), - String.class); - - assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertEquals("http://example.com/cb#error=invalid_scope&state=1234", response.getHeaders().get("Location").get(0)); - } - - @Test - public void oAuthAuthorizeValidRequest() { - - ResponseEntity response = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&response_type=token&scope=scope.test.1&state=1234"), + ResponseEntity response = restTemplate.exchange( + getUrlWithPort("/oauth/authorize?client_id=test&http://example.com/cb&response_type=token&scope=invalid&state=1234"), HttpMethod.GET, new HttpEntity(null, new HttpHeaders()), String.class); assertEquals(HttpStatus.FOUND, response.getStatusCode()); - assertTrue(response.getHeaders().get("Location").get(0).startsWith(getUrlWithPort("/#!/auth/"))); + assertEquals(INVALID_SCOPE_ERROR_URI, response.getHeaders().getFirst(HttpHeaders.LOCATION)); } private String getUrlWithPort(String url) { diff --git a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java new file mode 100644 index 0000000..2aea7af --- /dev/null +++ b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java @@ -0,0 +1,114 @@ +package net.identio.server.tests.integ.oauth; + +import net.identio.server.boot.IdentioServerApplication; +import net.identio.server.model.ProtocolType; +import net.identio.server.model.State; +import net.identio.server.model.api.AuthMethodResponse; +import net.identio.server.model.api.AuthSubmitRequest; +import net.identio.server.model.api.AuthSubmitResponse; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.*; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = IdentioServerApplication.class) +@TestPropertySource(properties = {"identio.config: src/test/resources/oauth-server-config/identio-config.yml", + "identio.public.fqdn: http://localhost:443", + "logging.config: src/test/resources/oauth-server-config/logback.xml"}) +public class OAuthImplicitFullCinematicTest { + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate = new TestRestTemplate(); + + private static final String AUTHENTICATION_URL = "/#!/auth/"; + + @Test + public void oAuthAuthorizeValidRequest() { + + ResponseEntity initialRequestResponse = restTemplate.exchange(getUrlWithPort("/oauth/authorize?client_id=test&redirect_uri=http://example.com/cb&response_type=token&scope=scope.test.1 scope.test.2&state=1234"), + HttpMethod.GET, + new HttpEntity<>(null, new HttpHeaders()), + String.class); + + // Redirect to the login page + String redirectUrl = initialRequestResponse.getHeaders().getFirst(HttpHeaders.LOCATION); + + assertEquals(HttpStatus.FOUND, initialRequestResponse.getStatusCode()); + assertTrue(redirectUrl.startsWith(getUrlWithPort(AUTHENTICATION_URL))); + + + // Extract session cookie and transactionId + String sessionIdCookie = getSessionCookie(initialRequestResponse); + String transactionId = getTransactionId(redirectUrl); + + assertTrue(sessionIdCookie.startsWith("identioSession=")); + assertNotNull(transactionId); + + // Request authentication methods + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.COOKIE, sessionIdCookie); + headers.add("X-Transaction-ID", transactionId); + + ResponseEntity authMethodResponse = restTemplate.exchange( + getUrlWithPort("/api/auth/methods"), + HttpMethod.GET, + new HttpEntity<>(null, headers), + AuthMethodResponse[].class); + + assertEquals(HttpStatus.OK, authMethodResponse.getStatusCode()); + assertEquals(authMethodResponse.getBody().length, 1); + assertEquals(authMethodResponse.getBody()[0].getName(), "Local"); + assertEquals(authMethodResponse.getBody()[0].getType(), "local"); + + // Authenticate with local method + AuthSubmitRequest authenticationSubmit = new AuthSubmitRequest().setLogin("johndoe").setPassword("password") + .setMethod("Local"); + + ResponseEntity authSubmitResponseEntity = restTemplate.exchange( + getUrlWithPort("/api/auth/submit/password"), + HttpMethod.POST, + new HttpEntity<>(authenticationSubmit, headers), + AuthSubmitResponse.class); + + // Check that the authentication is successful and that we get a response + AuthSubmitResponse authSubmitResponse = authSubmitResponseEntity.getBody(); + + assertEquals(HttpStatus.OK, authSubmitResponseEntity.getStatusCode()); + assertNotNull(authSubmitResponse); + + assertEquals(authSubmitResponse.getState(), State.RESPONSE); + assertEquals(authSubmitResponse.getProtocolType(), ProtocolType.OAUTH); + assertEquals(authSubmitResponse.getRelayState(), "1234"); + assertTrue(authSubmitResponse.getResponse().matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); + } + + + private String getUrlWithPort(String url) { + + return "http://localhost:" + port + url; + } + + private String getSessionCookie(ResponseEntity response) { + + return response.getHeaders().getFirst(HttpHeaders.SET_COOKIE); + } + + private String getTransactionId(String url) { + + return url.substring(getUrlWithPort(AUTHENTICATION_URL).length()); + } +} diff --git a/src/test/resources/oauth-server-config/identio-config.yml b/src/test/resources/oauth-server-config/identio-config.yml index c1fd202..38c6c9b 100644 --- a/src/test/resources/oauth-server-config/identio-config.yml +++ b/src/test/resources/oauth-server-config/identio-config.yml @@ -17,8 +17,10 @@ authorizationConfiguration: scopes: - name: scope.test.1 authLevel: *medium + expirationTime: 2400 - name: scope.test.2 authLevel: *strong + expirationTime: 3600 globalConfiguration: staticResourcesPath: ui/app From cb829fc4da933e03e7ba16cfc5982c42e71a9421 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Wed, 9 Aug 2017 01:11:05 +0200 Subject: [PATCH 026/104] Added JWT token verification to the integration test --- .../oauth/OAuthImplicitFullCinematicTest.java | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java index 2aea7af..dd2ac8f 100644 --- a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java @@ -1,5 +1,8 @@ package net.identio.server.tests.integ.oauth; +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; import net.identio.server.boot.IdentioServerApplication; import net.identio.server.model.ProtocolType; import net.identio.server.model.State; @@ -16,15 +19,20 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import java.io.FileInputStream; +import java.security.*; +import java.security.interfaces.RSAKey; +import java.util.Enumeration; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = IdentioServerApplication.class) @TestPropertySource(properties = {"identio.config: src/test/resources/oauth-server-config/identio-config.yml", - "identio.public.fqdn: http://localhost:443", + "identio.public.fqdn: https://localhost", "logging.config: src/test/resources/oauth-server-config/logback.xml"}) public class OAuthImplicitFullCinematicTest { @@ -94,6 +102,48 @@ public void oAuthAuthorizeValidRequest() { assertEquals(authSubmitResponse.getProtocolType(), ProtocolType.OAUTH); assertEquals(authSubmitResponse.getRelayState(), "1234"); assertTrue(authSubmitResponse.getResponse().matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); + + // Parse and validate JWT + Pattern pattern = Pattern.compile("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=(.*)&state=1234"); + Matcher matcher = pattern.matcher(authSubmitResponse.getResponse()); + + Algorithm algorithm = null; + try { + algorithm = Algorithm.RSA256(getPublicSigningKey()); + } catch (Exception e) { + fail(); + } + + JWTVerifier verifier = JWT.require(algorithm) + .withIssuer("https://localhost") + .withSubject("johndoe") + .withAudience("Test Client") + .withClaim("scope", "scope.test.1 scope.test.2") + .build(); + + if (matcher.find()) { + verifier.verify(matcher.group(1)); + } + else { + fail(); + } + + } + + private RSAKey getPublicSigningKey() throws Exception { + + FileInputStream fis = new FileInputStream( + "src/test/resources/oauth-server-config/default-sign-certificate.p12"); + + KeyStore ks = KeyStore.getInstance("PKCS12"); + ks.load(fis, "password".toCharArray()); + + Enumeration aliases = ks.aliases(); + + String alias = aliases.nextElement(); + + return (RSAKey) (ks.getCertificate(alias)).getPublicKey(); + } From 44dba5fc8b1ec632745adea32680b6612cc1587f Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Wed, 9 Aug 2017 01:34:39 +0200 Subject: [PATCH 027/104] Fixed some Codacy warnings --- .../mvc/common/GlobalControllerExceptionHandler.java | 2 -- .../net/identio/server/service/oauth/OAuthService.java | 9 ++++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index 3e0ecb2..6148235 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -20,11 +20,9 @@ License, or (at your option) any later version. package net.identio.server.mvc.common; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; import net.identio.server.exceptions.ServerException; import net.identio.server.exceptions.ValidationException; diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 57c8920..c6d6717 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -157,10 +157,9 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re public String generateSuccessResponse(AuthRequestValidationResult result, UserSession userSession) { - // http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600 StringBuilder responseBuilder = new StringBuilder(); - responseBuilder.append(result.getResponseUrl()).append("#"); + responseBuilder.append(result.getResponseUrl()).append("#expires_in="); // Determine expiration time of the authorization int expirationTime = -1; @@ -173,7 +172,7 @@ public String generateSuccessResponse(AuthRequestValidationResult result, UserSe } } - responseBuilder.append("expires_in=").append(expirationTime); + responseBuilder.append(expirationTime); // Calculate scope string StringBuilder scopeBuilder = new StringBuilder(); @@ -184,7 +183,7 @@ public String generateSuccessResponse(AuthRequestValidationResult result, UserSe scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { - responseBuilder.append("&token_type=Bearer"); + responseBuilder.append("&token_type=Bearer&access_token="); DateTime now = new DateTime(DateTimeZone.UTC); @@ -194,7 +193,7 @@ public String generateSuccessResponse(AuthRequestValidationResult result, UserSe .withJWTId(UUID.randomUUID().toString()).withClaim("scope", scopeBuilder.toString()) .sign(Algorithm.RSA256(signingKey)); - responseBuilder.append("&access_token=").append(accessToken); + responseBuilder.append(accessToken); } if (result.getRelayState() != null) { From ff2e801fa6496c0e7a81a633cb6077284a23ca37 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Thu, 17 Aug 2017 17:10:11 +0200 Subject: [PATCH 028/104] Major global refactoring - Removed shared states between components - Better separation in smaller classes - Make some bahaviours more explicit - Miscellaneous code cleanup --- .../server/boot/BootCustomizationBean.java | 29 +- .../boot/StaticResourceConfiguration.java | 5 +- .../server/exceptions/ServerException.java | 33 -- .../TransactionNotFoundException.java | 33 -- .../exceptions/ValidationException.java | 33 -- .../exceptions/WebSecurityException.java | 14 - .../net/identio/server/model/AuthMethod.java | 9 - .../server/model/AuthPolicyDecision.java | 60 --- .../model/AuthRequestValidationResult.java | 145 ------ .../net/identio/server/model/AuthSession.java | 12 +- .../identio/server/model/Authentication.java | 24 - .../model/AuthenticationResultStatus.java | 24 - .../server/model/AuthorizationScope.java | 7 + .../net/identio/server/model/ErrorStatus.java | 24 - .../server/model/SamlAuthentication.java | 2 + .../java/net/identio/server/model/State.java | 24 - .../server/model/StepUpAuthMethod.java | 42 -- .../identio/server/model/TransactionData.java | 99 ----- .../net/identio/server/model/UserDetail.java | 34 -- .../net/identio/server/model/UserSession.java | 5 +- .../server/model/ValidationResult.java | 97 ---- .../server/model/api/ApiErrorResponse.java | 52 --- .../server/model/api/AuthMethodResponse.java | 49 --- .../server/mvc/common/AuthentController.java | 204 +++++---- .../GlobalControllerExceptionHandler.java | 23 +- .../server/mvc/common/LogoController.java | 14 +- .../server/mvc/common/LogoutController.java | 3 +- .../server/mvc/common/PreAuthController.java | 87 ---- .../mvc/common/TransparentAuthController.java | 96 ++++ .../mvc/common/model/ApiErrorResponse.java | 42 ++ .../mvc/common/model/ApiResponseStatus.java | 26 ++ .../mvc/common/model/AuthMethodResponse.java | 50 +++ .../common/model}/AuthSubmitRequest.java | 37 +- .../common/model}/AuthSubmitResponse.java | 66 ++- .../LaunchSamlAuthenticationResponse.java | 45 +- .../server/mvc/oauth/ConsentController.java | 58 +++ .../server/mvc/oauth/OAuthController.java | 47 +- .../mvc/oauth/model/ConsentContext.java | 39 ++ .../mvc/oauth/model/ConsentRequest.java | 18 + .../mvc/oauth/model/ConsentResponse.java | 23 + .../mvc/saml/AssertionConsumerController.java | 42 +- .../server/mvc/saml/MetadataController.java | 16 +- .../mvc/saml/RequestConsumerController.java | 63 ++- .../server/mvc/saml/ResponderController.java | 16 +- .../AuthenticationProvider.java | 6 +- .../authentication/AuthenticationService.java | 13 +- .../ldap/LdapAuthenticationProvider.java | 62 ++- .../ldap/LdapConnectionFactory.java | 16 +- .../ldap/LdapSslSocketFactory.java | 20 +- .../local/LocalAuthenticationProvider.java | 38 +- .../authentication/model/Authentication.java | 25 ++ .../model/AuthenticationErrorStatus.java | 31 ++ .../model/AuthenticationResult.java | 46 +- .../model/AuthenticationResultStatus.java | 25 ++ .../model/UserPasswordAuthentication.java | 37 +- .../model/X509Authentication.java | 37 +- .../radius/RadiusAuthenticationProvider.java | 52 +-- .../saml/SamlAuthenticationProvider.java | 98 ++--- .../x509/X509AuthenticationProvider.java | 46 +- .../authorization/AuthorizationService.java | 15 +- .../service/authpolicy/AuthPolicyService.java | 110 ++--- .../authpolicy/model/AuthPolicyDecision.java | 61 +++ .../model/AuthPolicyDecisionStatus.java | 26 ++ .../configuration/ConfigurationService.java | 15 +- .../server/service/oauth/ConsentService.java | 62 +++ .../service/oauth/OAuthClientRepository.java | 2 +- .../server/service/oauth/OAuthService.java | 72 ++- .../FileOAuthClientRepository.java | 17 +- .../oauth/infrastructure/OAuthClientFile.java | 4 +- .../oauth}/model/OAuthClient.java | 49 ++- .../AuthOrchestrationService.java | 217 +++++++++ .../ProxyAuthOrchestrationService.java | 93 ++++ .../RequestOrchestrationService.java | 159 +++++++ .../exceptions/ServerException.java | 34 ++ .../exceptions/ValidationException.java | 34 ++ .../exceptions/WebSecurityException.java | 35 ++ .../model/AuthenticationValidationResult.java | 87 ++++ .../model/OrchestrationErrorStatus.java | 31 ++ .../model/RequestParsingInfo.java | 150 +++++++ .../model/RequestParsingStatus.java | 26 ++ .../model/RequestValidationResult.java | 75 ++++ .../orchestration/model/ResponseData.java | 56 +++ .../SamlAuthRequestGenerationResult.java | 43 +- .../orchestration/model/ValidationStatus.java | 26 ++ .../server/service/saml/MetadataService.java | 52 +-- .../server/service/saml/SamlService.java | 130 +++--- .../transaction/TransactionService.java | 44 +- .../transaction/model/TransactionData.java | 112 +++++ .../transaction/model/TransactionState.java | 26 ++ .../usersession/UserSessionService.java | 18 +- .../service/validation/ValidationService.java | 415 ------------------ .../net/identio/server/utils/DecodeUtils.java | 14 +- .../net/identio/server/utils/FileUtils.java | 4 +- .../identio/server/utils/PasswordUtils.java | 4 +- .../identio/server/utils/SecurityUtils.java | 4 +- .../oauth/OAuthImplicitFullCinematicTest.java | 58 ++- .../oauth-server-config/oauth-clients.yml | 1 + ui/app/scripts/app.js | 57 ++- ui/app/scripts/controllers/authController.js | 7 +- ui/app/scripts/controllers/errorController.js | 14 +- ui/app/scripts/directives/oauth-responder.js | 6 +- ui/app/scripts/directives/saml-responder.js | 6 +- ui/app/views/error.html | 18 +- ui/app/views/local.html | 7 + 104 files changed, 2669 insertions(+), 2250 deletions(-) delete mode 100644 src/main/java/net/identio/server/exceptions/ServerException.java delete mode 100644 src/main/java/net/identio/server/exceptions/TransactionNotFoundException.java delete mode 100644 src/main/java/net/identio/server/exceptions/ValidationException.java delete mode 100644 src/main/java/net/identio/server/exceptions/WebSecurityException.java delete mode 100644 src/main/java/net/identio/server/model/AuthPolicyDecision.java delete mode 100644 src/main/java/net/identio/server/model/AuthRequestValidationResult.java delete mode 100644 src/main/java/net/identio/server/model/Authentication.java delete mode 100644 src/main/java/net/identio/server/model/AuthenticationResultStatus.java delete mode 100644 src/main/java/net/identio/server/model/ErrorStatus.java delete mode 100644 src/main/java/net/identio/server/model/State.java delete mode 100644 src/main/java/net/identio/server/model/StepUpAuthMethod.java delete mode 100644 src/main/java/net/identio/server/model/TransactionData.java delete mode 100644 src/main/java/net/identio/server/model/UserDetail.java delete mode 100644 src/main/java/net/identio/server/model/ValidationResult.java delete mode 100644 src/main/java/net/identio/server/model/api/ApiErrorResponse.java delete mode 100644 src/main/java/net/identio/server/model/api/AuthMethodResponse.java delete mode 100644 src/main/java/net/identio/server/mvc/common/PreAuthController.java create mode 100644 src/main/java/net/identio/server/mvc/common/TransparentAuthController.java create mode 100644 src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java create mode 100644 src/main/java/net/identio/server/mvc/common/model/ApiResponseStatus.java create mode 100644 src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java rename src/main/java/net/identio/server/{model/api => mvc/common/model}/AuthSubmitRequest.java (53%) rename src/main/java/net/identio/server/{model/api => mvc/common/model}/AuthSubmitResponse.java (52%) rename src/main/java/net/identio/server/{model/api => mvc/common/model}/LaunchSamlAuthenticationResponse.java (60%) create mode 100644 src/main/java/net/identio/server/mvc/oauth/ConsentController.java create mode 100644 src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java create mode 100644 src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java create mode 100644 src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java create mode 100644 src/main/java/net/identio/server/service/authentication/model/Authentication.java create mode 100644 src/main/java/net/identio/server/service/authentication/model/AuthenticationErrorStatus.java rename src/main/java/net/identio/server/{ => service/authentication}/model/AuthenticationResult.java (56%) create mode 100644 src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java rename src/main/java/net/identio/server/{ => service/authentication}/model/UserPasswordAuthentication.java (51%) rename src/main/java/net/identio/server/{ => service/authentication}/model/X509Authentication.java (51%) create mode 100644 src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java create mode 100644 src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecisionStatus.java create mode 100644 src/main/java/net/identio/server/service/oauth/ConsentService.java rename src/main/java/net/identio/server/{ => service/oauth}/model/OAuthClient.java (53%) create mode 100644 src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java create mode 100644 src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java create mode 100644 src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java create mode 100644 src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java create mode 100644 src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java create mode 100644 src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/AuthenticationValidationResult.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/RequestParsingStatus.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/RequestValidationResult.java create mode 100644 src/main/java/net/identio/server/service/orchestration/model/ResponseData.java rename src/main/java/net/identio/server/{ => service/orchestration}/model/SamlAuthRequestGenerationResult.java (64%) create mode 100644 src/main/java/net/identio/server/service/orchestration/model/ValidationStatus.java create mode 100644 src/main/java/net/identio/server/service/transaction/model/TransactionData.java create mode 100644 src/main/java/net/identio/server/service/transaction/model/TransactionState.java delete mode 100644 src/main/java/net/identio/server/service/validation/ValidationService.java create mode 100644 ui/app/views/local.html diff --git a/src/main/java/net/identio/server/boot/BootCustomizationBean.java b/src/main/java/net/identio/server/boot/BootCustomizationBean.java index f76625d..ff913cc 100644 --- a/src/main/java/net/identio/server/boot/BootCustomizationBean.java +++ b/src/main/java/net/identio/server/boot/BootCustomizationBean.java @@ -19,17 +19,10 @@ License, or (at your option) any later version. */ package net.identio.server.boot; -import java.io.FileOutputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.TimeUnit; - +import net.identio.server.model.X509AuthMethod; +import net.identio.server.service.authentication.x509.X509AuthenticationProvider; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.utils.SecurityUtils; import org.apache.catalina.connector.Connector; import org.apache.coyote.http11.AbstractHttp11Protocol; import org.slf4j.Logger; @@ -41,10 +34,16 @@ License, or (at your option) any later version. import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import net.identio.server.model.X509AuthMethod; -import net.identio.server.service.authentication.x509.X509AuthenticationProvider; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.SecurityUtils; +import java.io.FileOutputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; @Configuration public class BootCustomizationBean { diff --git a/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java b/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java index be0c097..a511758 100644 --- a/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java +++ b/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java @@ -19,15 +19,14 @@ License, or (at your option) any later version. */ package net.identio.server.boot; -import java.io.File; - +import net.identio.server.service.configuration.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; -import net.identio.server.service.configuration.ConfigurationService; +import java.io.File; @Configuration public class StaticResourceConfiguration extends WebMvcConfigurerAdapter { diff --git a/src/main/java/net/identio/server/exceptions/ServerException.java b/src/main/java/net/identio/server/exceptions/ServerException.java deleted file mode 100644 index a425b8e..0000000 --- a/src/main/java/net/identio/server/exceptions/ServerException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.exceptions; - -public class ServerException extends Exception { - - private static final long serialVersionUID = 3342749474880290649L; - - public ServerException(String s) { - super(s); - } - - public ServerException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/exceptions/TransactionNotFoundException.java b/src/main/java/net/identio/server/exceptions/TransactionNotFoundException.java deleted file mode 100644 index 5a660e6..0000000 --- a/src/main/java/net/identio/server/exceptions/TransactionNotFoundException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.exceptions; - -public class TransactionNotFoundException extends Exception { - - private static final long serialVersionUID = -4769770317185612970L; - - public TransactionNotFoundException(String s) { - super(s); - } - - public TransactionNotFoundException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/exceptions/ValidationException.java b/src/main/java/net/identio/server/exceptions/ValidationException.java deleted file mode 100644 index 3144163..0000000 --- a/src/main/java/net/identio/server/exceptions/ValidationException.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.exceptions; - -public class ValidationException extends Exception { - - private static final long serialVersionUID = 974071100448457158L; - - public ValidationException(String s) { - super(s); - } - - public ValidationException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/exceptions/WebSecurityException.java b/src/main/java/net/identio/server/exceptions/WebSecurityException.java deleted file mode 100644 index 4cf56ee..0000000 --- a/src/main/java/net/identio/server/exceptions/WebSecurityException.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.identio.server.exceptions; - -public class WebSecurityException extends Exception { - - private static final long serialVersionUID = -5444195629811859215L; - - public WebSecurityException(String s) { - super(s); - } - - public WebSecurityException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/model/AuthMethod.java b/src/main/java/net/identio/server/model/AuthMethod.java index 05a38ee..3758479 100644 --- a/src/main/java/net/identio/server/model/AuthMethod.java +++ b/src/main/java/net/identio/server/model/AuthMethod.java @@ -26,7 +26,6 @@ public abstract class AuthMethod { private String name; private String logoFileName; private AuthLevel authLevel; - private StepUpAuthMethod stepUpAuthentication; protected String type; public boolean isExplicit() { @@ -57,14 +56,6 @@ public void setAuthLevel(AuthLevel authLevel) { this.authLevel = authLevel; } - public StepUpAuthMethod getStepUpAuthentication() { - return stepUpAuthentication; - } - - public void setStepUpAuthentication(StepUpAuthMethod stepUpAuthentication) { - this.stepUpAuthentication = stepUpAuthentication; - } - public String getType() { return type; } diff --git a/src/main/java/net/identio/server/model/AuthPolicyDecision.java b/src/main/java/net/identio/server/model/AuthPolicyDecision.java deleted file mode 100644 index 659b832..0000000 --- a/src/main/java/net/identio/server/model/AuthPolicyDecision.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -import java.util.HashSet; - -public class AuthPolicyDecision { - - private State nextState; - private AuthSession validatedAuthSession; - private HashSet nextAuthMethods; - - public AuthPolicyDecision(State nextState, AuthSession validatedAuthSession, HashSet nextAuthMethods) { - this.nextState = nextState; - this.validatedAuthSession = validatedAuthSession; - this.setNextAuthMethods(nextAuthMethods); - } - - public State getNextState() { - return nextState; - } - - public void setNextState(State nextState) { - this.nextState = nextState; - } - - public AuthSession getValidatedAuthSession() { - return validatedAuthSession; - } - - public void setValidatedAuthSession(AuthSession validatedAuthSession) { - this.validatedAuthSession = validatedAuthSession; - } - - public HashSet getNextAuthMethods() { - return nextAuthMethods; - } - - public void setNextAuthMethods(HashSet nextAuthMethods) { - this.nextAuthMethods = nextAuthMethods; - } - -} diff --git a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java b/src/main/java/net/identio/server/model/AuthRequestValidationResult.java deleted file mode 100644 index 00e3676..0000000 --- a/src/main/java/net/identio/server/model/AuthRequestValidationResult.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -import java.util.List; - -public class AuthRequestValidationResult { - - private boolean success; - private String errorStatus; - private String requestId; - private ProtocolType protocolType; - private String sourceApplicationName; - private boolean forceAuthentication; - private String authLevelComparison; - private List requestedAuthLevels; - private String relayState; - private String responseUrl; - private List requestedScopes; - private String responseType; - - public boolean isSuccess() { - return success; - } - - public AuthRequestValidationResult setSuccess(boolean success) { - this.success = success; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public AuthRequestValidationResult setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public String getRequestId() { - return requestId; - } - - public AuthRequestValidationResult setRequestId(String requestId) { - this.requestId = requestId; - return this; - } - - public ProtocolType getProtocolType() { - return protocolType; - } - - public AuthRequestValidationResult setProtocolType(ProtocolType protocolType) { - this.protocolType = protocolType; - return this; - } - - public String getSourceApplicationName() { - return sourceApplicationName; - } - - public AuthRequestValidationResult setSourceApplicationName(String sourceApplicationName) { - this.sourceApplicationName = sourceApplicationName; - return this; - } - - public boolean isForceAuthentication() { - return forceAuthentication; - } - - public AuthRequestValidationResult setForceAuthentication(boolean forceAuthentication) { - this.forceAuthentication = forceAuthentication; - return this; - } - - public String getAuthLevelComparison() { - return authLevelComparison; - } - - public AuthRequestValidationResult setAuthLevelComparison(String authLevelComparison) { - this.authLevelComparison = authLevelComparison; - return this; - } - - public List getRequestedAuthLevels() { - return requestedAuthLevels; - } - - public AuthRequestValidationResult setRequestedAuthLevels(List requestedAuthLevels) { - this.requestedAuthLevels = requestedAuthLevels; - return this; - } - - public String getRelayState() { - return relayState; - } - - public AuthRequestValidationResult setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getResponseUrl() { - return responseUrl; - } - - public AuthRequestValidationResult setResponseUrl(String responseUrl) { - this.responseUrl = responseUrl; - return this; - } - - public List getRequestedScopes() { - return requestedScopes; - } - - public AuthRequestValidationResult setRequestedScopes(List requestedScopes) { - this.requestedScopes = requestedScopes; - return this; - } - - public String getResponseType() { - return responseType; - } - - public void setResponseType(String responseType) { - this.responseType = responseType; - } -} diff --git a/src/main/java/net/identio/server/model/AuthSession.java b/src/main/java/net/identio/server/model/AuthSession.java index 7313b82..ec12623 100644 --- a/src/main/java/net/identio/server/model/AuthSession.java +++ b/src/main/java/net/identio/server/model/AuthSession.java @@ -26,13 +26,11 @@ public class AuthSession { private DateTime authInstant; private AuthMethod authMethod; - private StepUpAuthMethod stepUpAuthMethod; private AuthLevel authLevel; - public AuthSession(AuthMethod authMethod, StepUpAuthMethod stepUpAuthMethod, AuthLevel authLevel) { + public AuthSession(AuthMethod authMethod, AuthLevel authLevel) { this.authInstant = new DateTime(DateTimeZone.UTC); this.authMethod = authMethod; - this.stepUpAuthMethod = stepUpAuthMethod; this.authLevel = authLevel; } @@ -52,14 +50,6 @@ public void setAuthMethod(AuthMethod authMethod) { this.authMethod = authMethod; } - public StepUpAuthMethod getStepUpAuthMethod() { - return stepUpAuthMethod; - } - - public void setStepUpAuthMethod(StepUpAuthMethod stepUpAuthMethod) { - this.stepUpAuthMethod = stepUpAuthMethod; - } - public AuthLevel getAuthLevel() { return authLevel; } diff --git a/src/main/java/net/identio/server/model/Authentication.java b/src/main/java/net/identio/server/model/Authentication.java deleted file mode 100644 index e5b64fe..0000000 --- a/src/main/java/net/identio/server/model/Authentication.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public interface Authentication { - -} diff --git a/src/main/java/net/identio/server/model/AuthenticationResultStatus.java b/src/main/java/net/identio/server/model/AuthenticationResultStatus.java deleted file mode 100644 index 8e7a228..0000000 --- a/src/main/java/net/identio/server/model/AuthenticationResultStatus.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public enum AuthenticationResultStatus { - SUCCESS, FAIL, CHALLENGE -} diff --git a/src/main/java/net/identio/server/model/AuthorizationScope.java b/src/main/java/net/identio/server/model/AuthorizationScope.java index e626f6a..3df2df8 100644 --- a/src/main/java/net/identio/server/model/AuthorizationScope.java +++ b/src/main/java/net/identio/server/model/AuthorizationScope.java @@ -49,4 +49,11 @@ public void setExpirationTime(int expirationTime) { this.expirationTime = expirationTime; } + public AuthorizationScope getPublicCopy() { + AuthorizationScope response = new AuthorizationScope(); + response.setName(this.name); + + return response; + } + } diff --git a/src/main/java/net/identio/server/model/ErrorStatus.java b/src/main/java/net/identio/server/model/ErrorStatus.java deleted file mode 100644 index 9987ab4..0000000 --- a/src/main/java/net/identio/server/model/ErrorStatus.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public enum ErrorStatus { - AUTH_USER_ID_MISMATCH, AUTH_SAML_WRONG_AUDIENCE, AUTH_SAML_NO_RECIPIENT, AUTH_SAML_NO_DESTINATION, AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION, AUTH_SAML_CONDITIONS_NOT_MET, AUTH_SAML_INVALID_RESPONSE, AUTH_SAML_REJECTED_BY_PROXY, AUTH_SAML_NO_ASSERTION_IN_RESPONSE, AUTH_SAML_INVALID_INRESPONSETO, AUTH_USER_NOT_UNIQUE, AUTH_INVALID_CREDENTIALS, AUTH_TECHNICAL_ERROR, AUTH_NO_CREDENTIALS, AUTH_METHOD_UNKNOWN, AUTH_METHOD_NOT_ALLOWED -} diff --git a/src/main/java/net/identio/server/model/SamlAuthentication.java b/src/main/java/net/identio/server/model/SamlAuthentication.java index 3b6594d..0212243 100644 --- a/src/main/java/net/identio/server/model/SamlAuthentication.java +++ b/src/main/java/net/identio/server/model/SamlAuthentication.java @@ -19,6 +19,8 @@ License, or (at your option) any later version. */ package net.identio.server.model; +import net.identio.server.service.authentication.model.Authentication; + public class SamlAuthentication implements Authentication { private String response; diff --git a/src/main/java/net/identio/server/model/State.java b/src/main/java/net/identio/server/model/State.java deleted file mode 100644 index 0448d9e..0000000 --- a/src/main/java/net/identio/server/model/State.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public enum State { - AUTH, STEP_UP_AUTHENTICATION, RESPONSE, CONSENT, ERROR -} diff --git a/src/main/java/net/identio/server/model/StepUpAuthMethod.java b/src/main/java/net/identio/server/model/StepUpAuthMethod.java deleted file mode 100644 index 37edb67..0000000 --- a/src/main/java/net/identio/server/model/StepUpAuthMethod.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public class StepUpAuthMethod { - - private AuthMethod authMethod; - private AuthLevel authLevel; - - public AuthMethod getAuthMethod() { - return authMethod; - } - - public void setAuthMethod(AuthMethod authMethod) { - this.authMethod = authMethod; - } - - public AuthLevel getAuthLevel() { - return authLevel; - } - - public void setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - } -} diff --git a/src/main/java/net/identio/server/model/TransactionData.java b/src/main/java/net/identio/server/model/TransactionData.java deleted file mode 100644 index 7ed7b2c..0000000 --- a/src/main/java/net/identio/server/model/TransactionData.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -import java.util.ArrayList; -import java.util.HashSet; - -public class TransactionData { - - private String transactionId; - private UserSession userSession; - private AuthRequestValidationResult arValidationResult; - private ArrayList targetAuthLevels; - private HashSet targetAuthMethods = new HashSet<>(); - private AuthMethod selectedAuthMethod; - private State state; - private String samlProxyRequestId; - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; - } - - public UserSession getUserSession() { - return userSession; - } - - public void setUserSession(UserSession userSession) { - this.userSession = userSession; - } - - public AuthRequestValidationResult getArValidationResult() { - return arValidationResult; - } - - public void setArValidationResult(AuthRequestValidationResult arValidationResult) { - this.arValidationResult = arValidationResult; - } - - public ArrayList getTargetAuthLevels() { - return targetAuthLevels; - } - - public void setTargetAuthLevels(ArrayList targetAuthLevels) { - this.targetAuthLevels = targetAuthLevels; - } - - public HashSet getTargetAuthMethods() { - return targetAuthMethods; - } - - public void setTargetAuthMethods(HashSet targetAuthMethods) { - this.targetAuthMethods = targetAuthMethods; - } - - public AuthMethod getSelectedAuthMethod() { - return selectedAuthMethod; - } - - public void setSelectedAuthMethod(AuthMethod selectedAuthMethod) { - this.selectedAuthMethod = selectedAuthMethod; - } - - public State getState() { - return state; - } - - public void setState(State state) { - this.state = state; - } - - public String getSamlProxyRequestId() { - return samlProxyRequestId; - } - - public void setSamlProxyRequestId(String samlProxyRequestId) { - this.samlProxyRequestId = samlProxyRequestId; - } -} diff --git a/src/main/java/net/identio/server/model/UserDetail.java b/src/main/java/net/identio/server/model/UserDetail.java deleted file mode 100644 index dc9f2ec..0000000 --- a/src/main/java/net/identio/server/model/UserDetail.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public class UserDetail { - - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - -} diff --git a/src/main/java/net/identio/server/model/UserSession.java b/src/main/java/net/identio/server/model/UserSession.java index eca580d..b5a91df 100644 --- a/src/main/java/net/identio/server/model/UserSession.java +++ b/src/main/java/net/identio/server/model/UserSession.java @@ -61,9 +61,8 @@ public void setValidatedAuthMethods(HashSet validatedAuthMethods) { this.validatedAuthMethods = validatedAuthMethods; } - public AuthSession addAuthSession(String userId, AuthMethod authMethod, StepUpAuthMethod stepUpAuthMethod, - AuthLevel authLevel) { - AuthSession authSession = new AuthSession(authMethod, stepUpAuthMethod, authLevel); + public AuthSession addAuthSession(String userId, AuthMethod authMethod, AuthLevel authLevel) { + AuthSession authSession = new AuthSession(authMethod, authLevel); this.userId = userId; this.authSessions.add(authSession); this.validatedAuthMethods.add(authMethod); diff --git a/src/main/java/net/identio/server/model/ValidationResult.java b/src/main/java/net/identio/server/model/ValidationResult.java deleted file mode 100644 index 3d692a3..0000000 --- a/src/main/java/net/identio/server/model/ValidationResult.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; - -public class ValidationResult { - - private State state; - private ErrorStatus errorStatus; - private String responseData; - private AuthRequestValidationResult arValidationResult; - private String transactionId; - private String sessionId; - private String challengeType; - private String challengeValue; - - public State getState() { - return state; - } - - public ErrorStatus getErrorStatus() { - return errorStatus; - } - - public void setErrorStatus(ErrorStatus errorStatus) { - this.errorStatus = errorStatus; - } - - public void setState(State state) { - this.state = state; - } - - public String getResponseData() { - return responseData; - } - - public void setResponseData(String responseData) { - this.responseData = responseData; - } - - public AuthRequestValidationResult getArValidationResult() { - return arValidationResult; - } - - public void setArValidationResult(AuthRequestValidationResult arValidationResult) { - this.arValidationResult = arValidationResult; - } - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; - } - - public String getSessionId() { - return sessionId; - } - - public void setSessionId(String sessionId) { - this.sessionId = sessionId; - } - - public String getChallengeType() { - return challengeType; - } - - public void setChallengeType(String challengeType) { - this.challengeType = challengeType; - } - - public String getChallengeValue() { - return challengeValue; - } - - public void setChallengeValue(String challengeValue) { - this.challengeValue = challengeValue; - } - -} diff --git a/src/main/java/net/identio/server/model/api/ApiErrorResponse.java b/src/main/java/net/identio/server/model/api/ApiErrorResponse.java deleted file mode 100644 index 26ca8b2..0000000 --- a/src/main/java/net/identio/server/model/api/ApiErrorResponse.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model.api; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -@JsonInclude(Include.NON_NULL) -public class ApiErrorResponse { - - private String errorCode; - private String defaultMessage; - - public ApiErrorResponse(String errorCode, String defaultMessage) { - this.errorCode = errorCode; - this.defaultMessage = defaultMessage; - } - - public String getErrorCode() { - return errorCode; - } - - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; - } - - public String getDefaultMessage() { - return defaultMessage; - } - - public void setDefaultMessage(String defaultMessage) { - this.defaultMessage = defaultMessage; - } - -} diff --git a/src/main/java/net/identio/server/model/api/AuthMethodResponse.java b/src/main/java/net/identio/server/model/api/AuthMethodResponse.java deleted file mode 100644 index 7759dc1..0000000 --- a/src/main/java/net/identio/server/model/api/AuthMethodResponse.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model.api; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonInclude.Include; - -@JsonInclude(Include.NON_NULL) -public class AuthMethodResponse { - - private String name; - private String type; - - public String getName() { - return name; - } - - public AuthMethodResponse setName(String name) { - this.name = name; - return this; - } - - public String getType() { - return type; - } - - public AuthMethodResponse setType(String type) { - this.type = type; - return this; - } - -} diff --git a/src/main/java/net/identio/server/mvc/common/AuthentController.java b/src/main/java/net/identio/server/mvc/common/AuthentController.java index 4d29cca..a8b8054 100644 --- a/src/main/java/net/identio/server/mvc/common/AuthentController.java +++ b/src/main/java/net/identio/server/mvc/common/AuthentController.java @@ -19,129 +19,145 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.common; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.exceptions.SamlException; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.model.AuthMethod; +import net.identio.server.service.orchestration.model.SamlAuthRequestGenerationResult; +import net.identio.server.mvc.common.model.*; +import net.identio.server.service.authentication.model.UserPasswordAuthentication; +import net.identio.server.service.orchestration.AuthOrchestrationService; +import net.identio.server.service.orchestration.ProxyAuthOrchestrationService; +import net.identio.server.service.orchestration.model.AuthenticationValidationResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.ServletRequestBindingException; -import org.springframework.web.bind.annotation.CookieValue; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; -import net.identio.server.exceptions.SamlException; -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.SamlAuthRequestGenerationResult; -import net.identio.server.model.State; -import net.identio.server.model.UserPasswordAuthentication; -import net.identio.server.model.ValidationResult; -import net.identio.server.model.api.ApiErrorResponse; -import net.identio.server.model.api.AuthMethodResponse; -import net.identio.server.model.api.AuthSubmitRequest; -import net.identio.server.model.api.AuthSubmitResponse; -import net.identio.server.model.api.LaunchSamlAuthenticationResponse; -import net.identio.server.service.validation.ValidationService; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; @RestController public class AuthentController { - private static final Logger LOG = LoggerFactory.getLogger(AuthentController.class); + private static final Logger LOG = LoggerFactory.getLogger(AuthentController.class); + + @Autowired + private AuthOrchestrationService authOrchestrationService; + + @Autowired + private ProxyAuthOrchestrationService proxyAuthOrchestrationService; + + @RequestMapping(value = "/api/auth/submit/password", method = RequestMethod.POST) + public AuthSubmitResponse authenticationSubmit(HttpServletRequest httpRequest, + @RequestBody AuthSubmitRequest authSubmitRequest, HttpServletResponse httpResponse, + @RequestHeader(value = "X-Transaction-ID") String transactionId, + @CookieValue("identioSession") String sessionId) + throws ValidationException, WebSecurityException, ServerException { + + LOG.debug("Received authentication form"); + LOG.debug("* TransactionId: {}", transactionId); + + AuthSubmitResponse response = new AuthSubmitResponse(); + + UserPasswordAuthentication authentication = new UserPasswordAuthentication(authSubmitRequest.getLogin(), + authSubmitRequest.getPassword(), authSubmitRequest.getChallengeResponse()); + + AuthenticationValidationResult result = authOrchestrationService + .handleExplicitAuthentication(transactionId, sessionId, authSubmitRequest.getMethod(), authentication); + + switch (result.getValidationStatus()) { + + case RESPONSE: + + response.setStatus(ApiResponseStatus.RESPONSE) + .setDestinationUrl(result.getResponseData().getUrl()) + .setRelayState(result.getResponseData().getRelayState()) + .setData(result.getResponseData().getData()) + .setProtocolType(result.getProtocolType()); + break; - @Autowired - private ValidationService validationService; + case CHALLENGE: - @RequestMapping(value = "/api/auth/submit/password", method = RequestMethod.POST) - public AuthSubmitResponse authenticationSubmit(HttpServletRequest httpRequest, - @RequestBody AuthSubmitRequest authSubmitRequest, HttpServletResponse httpResponse, - @RequestHeader(value = "X-Transaction-ID") String transactionId, - @CookieValue("identioSession") String sessionId) throws ValidationException { + response.setStatus(ApiResponseStatus.CHALLENGE) + .setChallengeType(result.getChallengeType()) + .setChallengeValue(result.getChallengeValue()); + break; - LOG.debug("Received authentication form"); - LOG.debug("* TransactionId: {}", transactionId); + case ERROR: - UserPasswordAuthentication authentication = new UserPasswordAuthentication(authSubmitRequest.getLogin(), - authSubmitRequest.getPassword(), authSubmitRequest.getChallengeResponse()); + response.setStatus(ApiResponseStatus.ERROR) + .setErrorStatus(result.getErrorStatus()); + break; - ValidationResult result = validationService.validateExplicitAuthentication(transactionId, sessionId, - authSubmitRequest.getMethod(), authentication); + case CONSENT: - if (result.getState() == State.RESPONSE) { + response.setStatus(ApiResponseStatus.CONSENT); + break; - return new AuthSubmitResponse().setState(State.RESPONSE) - .setDestinationUrl(result.getArValidationResult().getResponseUrl()) - .setRelayState(result.getArValidationResult().getRelayState()).setResponse(result.getResponseData()) - .setProtocolType(result.getArValidationResult().getProtocolType()); - } + } - // Default response: authentication failed - return new AuthSubmitResponse().setState(result.getState()).setChallengeType(result.getChallengeType()) - .setChallengeValue(result.getChallengeValue()).setErrorStatus(result.getErrorStatus()); - } + return response; + } - @RequestMapping(value = "/api/auth/submit/saml", method = RequestMethod.POST) - public LaunchSamlAuthenticationResponse launchSamlAuthentication(HttpServletRequest httpRequest, - @RequestBody AuthSubmitRequest authSubmitRequest, HttpServletResponse httpResponse, - @RequestHeader(value = "X-Transaction-ID") String transactionId, - @CookieValue("identioSession") String sessionId) throws ValidationException { + @RequestMapping(value = "/api/auth/submit/saml", method = RequestMethod.POST) + public LaunchSamlAuthenticationResponse launchSamlAuthentication(HttpServletRequest httpRequest, + @RequestBody AuthSubmitRequest authSubmitRequest, HttpServletResponse httpResponse, + @RequestHeader(value = "X-Transaction-ID") String transactionId, + @CookieValue("identioSession") String sessionId) + throws ValidationException, WebSecurityException, ServerException { - LOG.debug("* Received authentication request to IDP {}", authSubmitRequest.getMethod()); + LOG.debug("* Received authentication request to IDP {}", authSubmitRequest.getMethod()); - SamlAuthRequestGenerationResult result = validationService.initSamlRequest(transactionId, sessionId, - authSubmitRequest.getMethod()); + SamlAuthRequestGenerationResult result = proxyAuthOrchestrationService + .initSamlRequest(transactionId, sessionId, authSubmitRequest.getMethod()); - if (result.isSuccess()) { - return new LaunchSamlAuthenticationResponse().setDestinationUrl(result.getTargetEndpoint().getLocation()) - .setBinding(result.getTargetEndpoint().getBinding()).setRelayState(result.getRelayState()) - .setSamlRequest(result.getSerializedRequest()).setSigAlg(result.getSignatureAlgorithm()) - .setSignature(result.getSignature()); - } + if (result.isSuccess()) { + return new LaunchSamlAuthenticationResponse().setDestinationUrl(result.getTargetEndpoint().getLocation()) + .setBinding(result.getTargetEndpoint().getBinding()).setRelayState(result.getRelayState()) + .setSamlRequest(result.getSerializedRequest()).setSigAlg(result.getSignatureAlgorithm()) + .setSignature(result.getSignature()); + } - return new LaunchSamlAuthenticationResponse().setErrorStatus(result.getErrorStatus()); - } + return new LaunchSamlAuthenticationResponse().setErrorStatus(result.getErrorStatus()); + } - @RequestMapping(value = "/api/auth/methods", method = RequestMethod.GET) - public List getAuthMethods(@RequestHeader(value = "X-Transaction-ID") String transactionId, - @CookieValue("identioSession") String sessionId) throws ValidationException { + @RequestMapping(value = "/api/auth/methods", method = RequestMethod.GET) + public List getAuthMethods(@RequestHeader(value = "X-Transaction-ID") String transactionId, + @CookieValue("identioSession") String sessionId) + throws WebSecurityException { - LOG.debug("Received authmethods list"); + LOG.debug("Received authmethods list"); - List list = new ArrayList(); + List list = new ArrayList(); - for (AuthMethod authMethod : validationService.getAuthMethods(transactionId, sessionId)) { - list.add(new AuthMethodResponse().setName(authMethod.getName()).setType(authMethod.getType())); - } + for (AuthMethod authMethod : authOrchestrationService.getAuthMethods(transactionId, sessionId)) { + list.add(new AuthMethodResponse().setName(authMethod.getName()).setType(authMethod.getType())); + } - return list; - } + return list; + } - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - @ExceptionHandler(ServerException.class) - public ApiErrorResponse handleServerException(SamlException e) { - return new ApiErrorResponse("error.server", e.getMessage()); - } + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + @ExceptionHandler(ServerException.class) + public ApiErrorResponse handleServerException(SamlException e) { + return new ApiErrorResponse(e.getMessage()); + } - @ResponseStatus(HttpStatus.BAD_REQUEST) - @ExceptionHandler(ValidationException.class) - public ApiErrorResponse handleValidationException(ValidationException e) { - return new ApiErrorResponse("error.validation", e.getMessage()); - } + @ResponseStatus(HttpStatus.BAD_REQUEST) + @ExceptionHandler(ValidationException.class) + public ApiErrorResponse handleValidationException(ValidationException e) { + return new ApiErrorResponse(e.getMessage()); + } - @ResponseStatus(HttpStatus.BAD_REQUEST) - @ExceptionHandler(ServletRequestBindingException.class) - public ApiErrorResponse handleServletRequestBindingException(ServletRequestBindingException e) { - return new ApiErrorResponse("error.mssing.parameter", e.getMessage()); - } + @ResponseStatus(HttpStatus.FORBIDDEN) + @ExceptionHandler(WebSecurityException.class) + public ApiErrorResponse handleWebSecurityException(WebSecurityException e) { + return new ApiErrorResponse(e.getMessage()); + } } diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index 6148235..218ce72 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -19,14 +19,14 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.common; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.ValidationException; - @ControllerAdvice public class GlobalControllerExceptionHandler { @@ -34,17 +34,18 @@ public class GlobalControllerExceptionHandler { private DefaultErrorController errorController; @ExceptionHandler(ServerException.class) - public String handleServerException() { - return errorController.displayErrorPage("error.server"); + public String handleServerException(ServerException e) { + return errorController.displayErrorPage(e.getMessage()); } @ExceptionHandler(ValidationException.class) - public String handleValidationException() { - return errorController.displayErrorPage("error.validation"); + public String handleValidationException(ValidationException e) { + return errorController.displayErrorPage(e.getMessage()); } - - @ExceptionHandler(ServletRequestBindingException.class) - public String handleServletRequestBindingException() { - return errorController.displayErrorPage("missing.parameter"); + + @ExceptionHandler(WebSecurityException.class) + public String handleWebSecurityException(WebSecurityException e) { + return errorController.displayErrorPage(e.getMessage()); } + } diff --git a/src/main/java/net/identio/server/mvc/common/LogoController.java b/src/main/java/net/identio/server/mvc/common/LogoController.java index 0765c95..9d19a41 100644 --- a/src/main/java/net/identio/server/mvc/common/LogoController.java +++ b/src/main/java/net/identio/server/mvc/common/LogoController.java @@ -19,13 +19,7 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.common; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.service.authpolicy.AuthPolicyService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -38,7 +32,11 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import net.identio.server.service.authpolicy.AuthPolicyService; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; @Controller public class LogoController { diff --git a/src/main/java/net/identio/server/mvc/common/LogoutController.java b/src/main/java/net/identio/server/mvc/common/LogoutController.java index f270869..25d45bc 100644 --- a/src/main/java/net/identio/server/mvc/common/LogoutController.java +++ b/src/main/java/net/identio/server/mvc/common/LogoutController.java @@ -19,6 +19,7 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.common; +import net.identio.server.service.usersession.UserSessionService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -27,8 +28,6 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import net.identio.server.service.usersession.UserSessionService; - @Controller public class LogoutController { diff --git a/src/main/java/net/identio/server/mvc/common/PreAuthController.java b/src/main/java/net/identio/server/mvc/common/PreAuthController.java deleted file mode 100644 index 5e6de88..0000000 --- a/src/main/java/net/identio/server/mvc/common/PreAuthController.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.mvc.common; - -import java.security.cert.X509Certificate; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; - -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.State; -import net.identio.server.model.ValidationResult; -import net.identio.server.model.X509Authentication; -import net.identio.server.mvc.saml.ResponderController; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.validation.ValidationService; -import net.identio.server.utils.HttpUtils; - -@Controller -public class PreAuthController { - - private static final Logger LOG = LoggerFactory.getLogger(PreAuthController.class); - - @Autowired - private ValidationService validationService; - @Autowired - private ResponderController responderController; - @Autowired - private ConfigurationService configurationService; - - public String checkTransparentAuthentication(HttpServletRequest httpRequest, HttpServletResponse httpResponse, - ValidationResult result) throws ServerException, ValidationException { - - // We check if the user was authenticated with a X509 certificate - Object clientAuthCerts = httpRequest.getAttribute("javax.servlet.request.X509Certificate"); - - String userCert = HttpUtils.getHttpHeader(httpRequest, "X-User-Cert"); - String sharedSecret = HttpUtils.getHttpHeader(httpRequest, "X-Shared-Secret"); - - X509Authentication authentication = null; - - if (clientAuthCerts != null || userCert != null && sharedSecret != null) { - authentication = new X509Authentication((X509Certificate[]) clientAuthCerts, userCert, sharedSecret); - } - - ValidationResult validationResult = validationService.validateTransparentAuthentication(result, authentication); - - if (validationResult.getState() == State.RESPONSE) { - - String responseView = responderController.displayResponderPage( - result.getArValidationResult().getResponseUrl(), result.getResponseData(), - result.getArValidationResult().getRelayState(), result.getSessionId(), httpResponse); - return responseView; - - } else { - LOG.debug("Displaying authentication page"); - - HttpUtils.setSessionCookie(httpResponse, result.getSessionId(), - configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - - return "redirect:/#!/auth/" + validationResult.getTransactionId(); - } - } -} diff --git a/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java new file mode 100644 index 0000000..0b4c422 --- /dev/null +++ b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java @@ -0,0 +1,96 @@ +/* + This file is part of Ident.io + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.mvc.common; + +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.service.authentication.model.X509Authentication; +import net.identio.server.mvc.saml.ResponderController; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.orchestration.AuthOrchestrationService; +import net.identio.server.service.orchestration.model.AuthenticationValidationResult; +import net.identio.server.service.orchestration.model.ValidationStatus; +import net.identio.server.utils.HttpUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.security.cert.X509Certificate; + +@Controller +public class TransparentAuthController { + + private static final Logger LOG = LoggerFactory.getLogger(TransparentAuthController.class); + + @Autowired + private AuthOrchestrationService authOrchestrationService; + @Autowired + private ResponderController responderController; + @Autowired + private ConfigurationService configurationService; + + public String checkTransparentAuthentication(HttpServletRequest httpRequest, HttpServletResponse httpResponse, + String sessionId, String transactionId) + throws ServerException, WebSecurityException { + + // We check if the user was authenticated with a X509 certificate + Object clientAuthCerts = httpRequest.getAttribute("javax.servlet.request.X509Certificate"); + + String userCert = HttpUtils.getHttpHeader(httpRequest, "X-User-Cert"); + String sharedSecret = HttpUtils.getHttpHeader(httpRequest, "X-Shared-Secret"); + + X509Authentication authentication; + + if (clientAuthCerts != null || userCert != null && sharedSecret != null) { + authentication = new X509Authentication((X509Certificate[]) clientAuthCerts, userCert, sharedSecret); + } + else { + return redirectToAuthenticationPage(httpResponse, sessionId, transactionId); + } + + AuthenticationValidationResult result = authOrchestrationService.handleTransparentAuthentication( + authentication, sessionId, transactionId); + + if (result.getValidationStatus() == ValidationStatus.RESPONSE) { + + return responderController.displayResponderPage( + result.getResponseData().getUrl(), result.getResponseData().getData(), + result.getResponseData().getRelayState(), sessionId, httpResponse); + + } else { + return redirectToAuthenticationPage(httpResponse, sessionId, transactionId); + } + } + + private String redirectToAuthenticationPage(HttpServletResponse httpResponse, String sessionId, + String transactionId) { + LOG.debug("Displaying authentication page"); + + HttpUtils.setSessionCookie(httpResponse, sessionId, + configurationService.getConfiguration().getGlobalConfiguration().isSecure()); + + return "redirect:/#!/auth/" + transactionId; + } + +} diff --git a/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java b/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java new file mode 100644 index 0000000..d01c8fa --- /dev/null +++ b/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java @@ -0,0 +1,42 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.mvc.common.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +@JsonInclude(Include.NON_NULL) +public class ApiErrorResponse { + + private String errorCode; + + public ApiErrorResponse(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } +} diff --git a/src/main/java/net/identio/server/mvc/common/model/ApiResponseStatus.java b/src/main/java/net/identio/server/mvc/common/model/ApiResponseStatus.java new file mode 100644 index 0000000..b1f73ec --- /dev/null +++ b/src/main/java/net/identio/server/mvc/common/model/ApiResponseStatus.java @@ -0,0 +1,26 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.mvc.common.model; + +public enum ApiResponseStatus { + CHALLENGE, ERROR, CONSENT, RESPONSE +} diff --git a/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java b/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java new file mode 100644 index 0000000..32d161a --- /dev/null +++ b/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java @@ -0,0 +1,50 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.mvc.common.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +@JsonInclude(Include.NON_NULL) +public class AuthMethodResponse { + + private String name; + private String type; + + public String getName() { + return name; + } + + public AuthMethodResponse setName(String name) { + this.name = name; + return this; + } + + public String getType() { + return type; + } + + public AuthMethodResponse setType(String type) { + this.type = type; + return this; + } + +} diff --git a/src/main/java/net/identio/server/model/api/AuthSubmitRequest.java b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java similarity index 53% rename from src/main/java/net/identio/server/model/api/AuthSubmitRequest.java rename to src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java index 8e33bef..e45eb69 100644 --- a/src/main/java/net/identio/server/model/api/AuthSubmitRequest.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java @@ -1,23 +1,24 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model.api; +package net.identio.server.mvc.common.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; diff --git a/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java similarity index 52% rename from src/main/java/net/identio/server/model/api/AuthSubmitResponse.java rename to src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java index 4507a78..1f9cb4c 100644 --- a/src/main/java/net/identio/server/model/api/AuthSubmitResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java @@ -1,57 +1,55 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model.api; +package net.identio.server.mvc.common.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; - -import net.identio.server.model.ErrorStatus; import net.identio.server.model.ProtocolType; -import net.identio.server.model.State; @JsonInclude(Include.NON_NULL) public class AuthSubmitResponse { - private State state; - private ErrorStatus errorStatus; + private ApiResponseStatus status; + private String errorStatus; private String destinationUrl; private String relayState; - private String response; + private String data; private ProtocolType protocolType; private String challengeType; private String challengeValue; - public State getState() { - return state; + public ApiResponseStatus getStatus() { + return status; } - public AuthSubmitResponse setState(State state) { - this.state = state; + public AuthSubmitResponse setStatus(ApiResponseStatus status) { + this.status = status; return this; } - public ErrorStatus getErrorStatus() { + public String getErrorStatus() { return errorStatus; } - public AuthSubmitResponse setErrorStatus(ErrorStatus errorStatus) { + public AuthSubmitResponse setErrorStatus(String errorStatus) { this.errorStatus = errorStatus; return this; } @@ -74,12 +72,12 @@ public AuthSubmitResponse setRelayState(String relayState) { return this; } - public String getResponse() { - return response; + public String getData() { + return data; } - public AuthSubmitResponse setResponse(String response) { - this.response = response; + public AuthSubmitResponse setData(String data) { + this.data = data; return this; } diff --git a/src/main/java/net/identio/server/model/api/LaunchSamlAuthenticationResponse.java b/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java similarity index 60% rename from src/main/java/net/identio/server/model/api/LaunchSamlAuthenticationResponse.java rename to src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java index bd4661a..c0338cd 100644 --- a/src/main/java/net/identio/server/model/api/LaunchSamlAuthenticationResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java @@ -1,34 +1,33 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model.api; +package net.identio.server.mvc.common.model; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; -import net.identio.server.model.ErrorStatus; - @JsonInclude(Include.NON_NULL) public class LaunchSamlAuthenticationResponse { private String destinationUrl; - private ErrorStatus errorStatus; + private String errorStatus; private String binding; private String relayState; private String samlRequest; @@ -44,11 +43,11 @@ public LaunchSamlAuthenticationResponse setDestinationUrl(String destinationUrl) return this; } - public ErrorStatus getErrorStatus() { + public String getErrorStatus() { return errorStatus; } - public LaunchSamlAuthenticationResponse setErrorStatus(ErrorStatus errorStatus) { + public LaunchSamlAuthenticationResponse setErrorStatus(String errorStatus) { this.errorStatus = errorStatus; return this; } diff --git a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java new file mode 100644 index 0000000..9cd372c --- /dev/null +++ b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java @@ -0,0 +1,58 @@ +/* + This file is part of Ident.io + + Ident.io - A flexible authentication server + Copyright (C) Loeiz TANGUY + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as + published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +package net.identio.server.mvc.oauth; + +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.mvc.oauth.model.ConsentContext; +import net.identio.server.mvc.oauth.model.ConsentRequest; +import net.identio.server.mvc.oauth.model.ConsentResponse; +import net.identio.server.service.oauth.ConsentService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +public class ConsentController { + + private static final Logger LOG = LoggerFactory.getLogger(ConsentController.class); + + @Autowired + private ConsentService consentService; + + @RequestMapping(value = "/api/authz/consent", method = RequestMethod.GET) + public ConsentContext getConsentContext(@RequestHeader(value = "X-Transaction-ID") String transactionId, + @CookieValue("identioSession") String sessionId) + throws ValidationException, WebSecurityException { + + + return consentService.getConsentContext(transactionId, sessionId); + } + + @RequestMapping(value = "/api/authz/consent", method = RequestMethod.POST) + public ConsentResponse receiveConsent(@RequestBody ConsentRequest consentRequest, + @RequestHeader(value = "X-Transaction-ID") String transactionId, + @CookieValue("identioSession") String sessionId) { + + return new ConsentResponse(); + } + +} diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index 65ea4c3..2457f1e 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -19,13 +19,13 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.oauth; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.model.OAuthInboundRequest; +import net.identio.server.mvc.common.TransparentAuthController; +import net.identio.server.service.orchestration.RequestOrchestrationService; +import net.identio.server.service.orchestration.model.RequestValidationResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -35,12 +35,11 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.model.ValidationResult; -import net.identio.server.mvc.common.PreAuthController; -import net.identio.server.service.validation.ValidationService; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; @Controller public class OAuthController { @@ -48,18 +47,20 @@ public class OAuthController { private static final Logger LOG = LoggerFactory.getLogger(OAuthController.class); @Autowired - private ValidationService validationService; + private RequestOrchestrationService validationService; @Autowired - private PreAuthController preAuthController; + private TransparentAuthController transparentAuthController; @RequestMapping(value = "/oauth/authorize", method = RequestMethod.GET) - public String authorizeRequest(@RequestParam(value = "response_type", required = false) String responseType, + public String authorizeRequest( + @RequestParam(value = "response_type", required = false) String responseType, @RequestParam(value = "client_id", required = false) String clientId, @RequestParam(value = "redirect_uri", required = false) String redirectUri, @RequestParam(value = "scope", required = false) String scopes, @RequestParam(value = "state", required = false) String state, @CookieValue(required = false) String identioSession, - HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ValidationException, ServerException { + HttpServletRequest httpRequest, + HttpServletResponse httpResponse) throws ValidationException, ServerException, WebSecurityException { LOG.info("Received OAuth authorization request from ClientId: {}", clientId); LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); @@ -73,19 +74,21 @@ public String authorizeRequest(@RequestParam(value = "response_type", required = OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesList, state); - ValidationResult result = validationService.validateAuthentRequest(request, identioSession); + RequestValidationResult result = validationService.validateRequest(request, identioSession); - switch (result.getState()) { + switch (result.getValidationStatus()) { case RESPONSE: - return "redirect:" + result.getResponseData(); + return "redirect:" + result.getResponseData().getUrl(); case CONSENT: return "redirect:/#!/consent/"; case ERROR: - return "redirect:/#!/error/" + result.getArValidationResult().getErrorStatus(); + return "redirect:/#!/error/" + result.getErrorStatus(); + default: - return preAuthController.checkTransparentAuthentication(httpRequest, httpResponse, result); + return transparentAuthController.checkTransparentAuthentication( + httpRequest, httpResponse, result.getSessionId(), result.getTransactionId()); } } diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java new file mode 100644 index 0000000..77461a2 --- /dev/null +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java @@ -0,0 +1,39 @@ +package net.identio.server.mvc.oauth.model; + +import net.identio.server.model.AuthorizationScope; + +import java.util.List; + +public class ConsentContext { + + private String audience; + private String audienceLogo; + private List requestedScopes; + + public String getAudience() { + return audience; + } + + public ConsentContext setAudience(String audience) { + this.audience = audience; + return this; + } + + public String getAudienceLogo() { + return audienceLogo; + } + + public ConsentContext setAudienceLogo(String audienceLogo) { + this.audienceLogo = audienceLogo; + return this; + } + + public List getRequestedScopes() { + return requestedScopes; + } + + public ConsentContext setRequestedScopes(List requestedScopes) { + this.requestedScopes = requestedScopes; + return this; + } +} diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java new file mode 100644 index 0000000..af93830 --- /dev/null +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java @@ -0,0 +1,18 @@ +package net.identio.server.mvc.oauth.model; + +import java.util.List; + +public class ConsentRequest { + + private List approvedScopes; + + + public List getApprovedScopes() { + return approvedScopes; + } + + public ConsentRequest setApprovedScopes(List approvedScopes) { + this.approvedScopes = approvedScopes; + return this; + } +} diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java new file mode 100644 index 0000000..5d46e44 --- /dev/null +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java @@ -0,0 +1,23 @@ +package net.identio.server.mvc.oauth.model; + +public class ConsentResponse { + + private boolean success; + private String response; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getResponse() { + return response; + } + + public void setResponse(String response) { + this.response = response; + } +} diff --git a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java index 9fcdd3c..b13254a 100644 --- a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java @@ -19,9 +19,15 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.saml; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.model.SamlAuthentication; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.orchestration.AuthOrchestrationService; +import net.identio.server.service.orchestration.model.AuthenticationValidationResult; +import net.identio.server.service.orchestration.model.ValidationStatus; +import net.identio.server.utils.HttpUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,14 +38,8 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.util.HtmlUtils; -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.SamlAuthentication; -import net.identio.server.model.State; -import net.identio.server.model.ValidationResult; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.validation.ValidationService; -import net.identio.server.utils.HttpUtils; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; @Controller public class AssertionConsumerController { @@ -47,7 +47,7 @@ public class AssertionConsumerController { private static final Logger LOG = LoggerFactory.getLogger(AssertionConsumerController.class); @Autowired - private ValidationService validationService; + private AuthOrchestrationService authOrchestrationService; @Autowired private ConfigurationService configurationService; @@ -59,33 +59,33 @@ public class AssertionConsumerController { public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, @RequestParam("SAMLResponse") String usSamlResponse, @RequestParam(value = "RelayState", required = false) String usRelayState, - @CookieValue String identioSession) throws ValidationException, ServerException { + @CookieValue String identioSession) throws ValidationException, ServerException, WebSecurityException { LOG.debug("Received SAML response on /SAML2/ACS/POST"); LOG.debug("* SAMLResponse: {}", usSamlResponse); LOG.debug("* RelayState: {}", usRelayState); // To prevent XSS attacks, we escape the RelayState value - String decodedRelayState = HtmlUtils.htmlEscape(usRelayState); + String transactionId = HtmlUtils.htmlEscape(usRelayState); SamlAuthentication authentication = new SamlAuthentication(usSamlResponse); - ValidationResult result = validationService.validateExplicitAuthentication(decodedRelayState, identioSession, - null, authentication); + AuthenticationValidationResult result = authOrchestrationService + .handleExplicitAuthentication(transactionId, identioSession, null, authentication); - if (result.getState() == State.RESPONSE) { + if (result.getValidationStatus() == ValidationStatus.RESPONSE) { String responseView = responderController.displayResponderPage( - result.getArValidationResult().getResponseUrl(), result.getResponseData(), - result.getArValidationResult().getRelayState(), result.getSessionId(), httpResponse); + result.getResponseData().getUrl(), result.getResponseData().getData(), + result.getResponseData().getRelayState(), identioSession, httpResponse); return responseView; } else { LOG.debug("Displaying authentication page"); - HttpUtils.setSessionCookie(httpResponse, result.getSessionId(), + HttpUtils.setSessionCookie(httpResponse, identioSession, configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - return "redirect:/#!/auth/" + result.getTransactionId(); + return "redirect:/#!/auth/" + transactionId; } } diff --git a/src/main/java/net/identio/server/mvc/saml/MetadataController.java b/src/main/java/net/identio/server/mvc/saml/MetadataController.java index 5ac4282..8dfc462 100644 --- a/src/main/java/net/identio/server/mvc/saml/MetadataController.java +++ b/src/main/java/net/identio/server/mvc/saml/MetadataController.java @@ -19,11 +19,8 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.saml; -import java.io.IOException; -import java.io.Writer; - -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.saml.MetadataService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -31,8 +28,9 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import net.identio.server.exceptions.ServerException; -import net.identio.server.service.saml.MetadataService; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Writer; @Controller public class MetadataController { @@ -50,10 +48,10 @@ public void getIdpMetadata(HttpServletResponse httpResponse) throws ServerExcept String returnValue = metadataService.getIdpMetadata().toString(); httpResponse.setContentType("application/samlmetadata+xml"); - httpResponse.setContentLength((int) returnValue.length()); + httpResponse.setContentLength(returnValue.length()); httpResponse.setHeader("Content-Disposition", "attachment; filename=\"identio-idp-metadata.xml\""); - try (Writer writer = httpResponse.getWriter();) { + try (Writer writer = httpResponse.getWriter()) { writer.write(returnValue); writer.flush(); diff --git a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java index 5907071..080d1ab 100644 --- a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java @@ -19,12 +19,17 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.saml; -import java.io.IOException; -import java.util.zip.DataFormatException; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import net.identio.saml.SamlConstants; +import net.identio.server.exceptions.*; +import net.identio.server.model.SamlInboundRequest; +import net.identio.server.mvc.common.TransparentAuthController; +import net.identio.server.service.orchestration.RequestOrchestrationService; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.service.orchestration.model.ValidationStatus; +import net.identio.server.service.orchestration.model.RequestValidationResult; +import net.identio.server.utils.DecodeUtils; import org.apache.xml.security.exceptions.Base64DecodingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,18 +41,10 @@ License, or (at your option) any later version. import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.util.HtmlUtils; -import net.identio.saml.SamlConstants; -import net.identio.server.exceptions.NoAuthMethodFoundException; -import net.identio.server.exceptions.SamlException; -import net.identio.server.exceptions.ServerException; -import net.identio.server.exceptions.UnknownAuthLevelException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.SamlInboundRequest; -import net.identio.server.model.State; -import net.identio.server.model.ValidationResult; -import net.identio.server.mvc.common.PreAuthController; -import net.identio.server.service.validation.ValidationService; -import net.identio.server.utils.DecodeUtils; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.zip.DataFormatException; @Controller public class RequestConsumerController { @@ -55,9 +52,9 @@ public class RequestConsumerController { private static final Logger LOG = LoggerFactory.getLogger(RequestConsumerController.class); @Autowired - private ValidationService validationService; + private RequestOrchestrationService validationService; @Autowired - private PreAuthController preAuthController; + private TransparentAuthController transparentAuthController; @Autowired private ResponderController responderController; @@ -65,10 +62,10 @@ public class RequestConsumerController { public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, @RequestParam("SAMLRequest") String usSamlRequest, @RequestParam(value = "RelayState", required = false) String usRelayState, - @CookieValue(required = false) String identioSession) throws ServerException, ValidationException { + @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { - String decodedSamlRequest = null; - String decodedRelayState = null; + String decodedSamlRequest; + String decodedRelayState; LOG.debug("Received request on /SAML2/SSO/POST"); LOG.debug("* SAMLRequest: {}", usSamlRequest); @@ -105,7 +102,7 @@ public String samlConsumerRedirect(HttpServletRequest httpRequest, HttpServletRe @RequestParam(value = "RelayState", required = false) String usRelayState, @RequestParam(value = "SigAlg", required = false) String usSigAlg, @RequestParam(value = "Signature", required = false) String usSignature, - @CookieValue(required = false) String identioSession) throws ServerException, ValidationException { + @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { String signedInfo = null; String decodedSamlRequest = null; @@ -166,25 +163,25 @@ public String samlConsumerRedirect(HttpServletRequest httpRequest, HttpServletRe private String processRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String binding, String request, String relayState, String sigAlg, String signatureValue, String signedInfo, - String sessionId) throws ServerException, ValidationException { + String sessionId) throws ServerException, ValidationException, WebSecurityException { LOG.debug("Processing SAML authentication request."); SamlInboundRequest samlRequest = new SamlInboundRequest(binding, request, signatureValue, signedInfo, sigAlg, relayState); - // The request is forwarded to the validation service - ValidationResult result = validationService.validateAuthentRequest(samlRequest, sessionId); + // The request is forwarded to the orchestration service + RequestValidationResult result = validationService.validateRequest(samlRequest, sessionId); - if (result.getState() == State.RESPONSE) { + if (result.getValidationStatus() == ValidationStatus.RESPONSE) { - String responseView = responderController.displayResponderPage( - result.getArValidationResult().getResponseUrl(), result.getResponseData(), - samlRequest.getRelayState(), result.getSessionId(), httpResponse); - return responseView; + return responderController.displayResponderPage( + result.getResponseData().getUrl(), result.getResponseData().getData(), + result.getResponseData().getRelayState(), result.getSessionId(), httpResponse); } else { - return preAuthController.checkTransparentAuthentication(httpRequest, httpResponse, result); + return transparentAuthController.checkTransparentAuthentication(httpRequest, httpResponse, + result.getSessionId(), result.getTransactionId()); } } diff --git a/src/main/java/net/identio/server/mvc/saml/ResponderController.java b/src/main/java/net/identio/server/mvc/saml/ResponderController.java index 4df0be2..21874c0 100644 --- a/src/main/java/net/identio/server/mvc/saml/ResponderController.java +++ b/src/main/java/net/identio/server/mvc/saml/ResponderController.java @@ -19,19 +19,17 @@ License, or (at your option) any later version. */ package net.identio.server.mvc.saml; -import java.io.IOException; -import java.io.Writer; - -import javax.servlet.http.HttpServletResponse; - +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.utils.HttpUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; -import net.identio.server.exceptions.ServerException; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.HttpUtils; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Writer; @Controller public class ResponderController { @@ -56,7 +54,7 @@ public String displayResponderPage(String destinationUrl, String responseData, S httpResponse.setContentType("text/html"); - try (Writer writer = httpResponse.getWriter();) { + try (Writer writer = httpResponse.getWriter()) { writer.write(responseForm); writer.flush(); diff --git a/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java index 9ff9a20..b4eb2dd 100644 --- a/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java @@ -20,9 +20,9 @@ License, or (at your option) any later version. package net.identio.server.service.authentication; import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.TransactionData; +import net.identio.server.service.authentication.model.Authentication; +import net.identio.server.service.authentication.model.AuthenticationResult; +import net.identio.server.service.transaction.model.TransactionData; public interface AuthenticationProvider { diff --git a/src/main/java/net/identio/server/service/authentication/AuthenticationService.java b/src/main/java/net/identio/server/service/authentication/AuthenticationService.java index 7e527d0..4d6b66b 100644 --- a/src/main/java/net/identio/server/service/authentication/AuthenticationService.java +++ b/src/main/java/net/identio/server/service/authentication/AuthenticationService.java @@ -19,17 +19,16 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication; -import java.util.HashMap; - +import net.identio.server.model.*; +import net.identio.server.service.authentication.model.Authentication; +import net.identio.server.service.authentication.model.AuthenticationResult; +import net.identio.server.service.authentication.model.AuthenticationResultStatus; +import net.identio.server.service.transaction.model.TransactionData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.TransactionData; +import java.util.HashMap; @Service public class AuthenticationService { diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java index 6d48f77..ccedff0 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java @@ -19,6 +19,25 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.ldap; +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.*; +import net.identio.server.service.authentication.AuthenticationProvider; +import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.*; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.utils.SecurityUtils; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import javax.naming.NamingEnumeration; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.ldap.InitialLdapContext; import java.io.IOException; import java.security.KeyManagementException; import java.security.KeyStore; @@ -28,33 +47,6 @@ License, or (at your option) any later version. import java.util.HashMap; import java.util.List; -import javax.naming.NamingEnumeration; -import javax.naming.directory.SearchControls; -import javax.naming.directory.SearchResult; -import javax.naming.ldap.InitialLdapContext; - -import org.apache.commons.pool2.impl.GenericObjectPool; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Service; - -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.LdapAuthMethod; -import net.identio.server.model.LdapPoolConfig; -import net.identio.server.model.TransactionData; -import net.identio.server.model.UserPasswordAuthentication; -import net.identio.server.service.authentication.AuthenticationProvider; -import net.identio.server.service.authentication.AuthenticationService; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.SecurityUtils; - @Service @Scope("singleton") public class LdapAuthenticationProvider implements AuthenticationProvider { @@ -88,12 +80,12 @@ public LdapAuthenticationProvider(ConfigurationService configurationService, } public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + TransactionData transactionData) { LdapAuthMethod ldapAuthMethod = (LdapAuthMethod) authMethod; UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; - boolean validation = false; + boolean validation; String userId = userPwAuthentication.getUserId(); String password = userPwAuthentication.getPassword(); @@ -114,7 +106,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe NamingEnumeration results = ctx.search(ldapAuthMethod.getBaseDn(), searchFilter, controls); - SearchResult result = null; + SearchResult result; if (results.hasMoreElements()) { result = results.next(); @@ -122,12 +114,12 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (results.hasMoreElements()) { LOG.error("User ID {} is not unique in LDAP {}", userId, authMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_USER_NOT_UNIQUE); + .setErrorStatus(AuthenticationErrorStatus.USER_NOT_UNIQUE); } } else { LOG.error("User ID {} does not exist in LDAP {}", userId, authMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } // Try to bind with the found user id @@ -143,7 +135,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe } else { LOG.error("Authentication failed for user {} with {}", userId, authMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } } catch (Exception ex) { @@ -158,7 +150,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe } return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_TECHNICAL_ERROR); + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); } } @@ -173,7 +165,7 @@ private void initPool(List ldapAuthMethods) { LdapConnectionFactory factory = new LdapConnectionFactory(ldapAuthMethod); - GenericObjectPool pool = new GenericObjectPool(factory); + GenericObjectPool pool = new GenericObjectPool<>(factory); LdapPoolConfig poolConfig = ldapAuthMethod.getPoolConfig(); diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java index 4167f29..0a76ecf 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java @@ -19,21 +19,19 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.ldap; -import java.util.Hashtable; - -import javax.naming.CommunicationException; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.directory.SearchControls; -import javax.naming.ldap.InitialLdapContext; - +import net.identio.server.model.LdapAuthMethod; import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import net.identio.server.model.LdapAuthMethod; +import javax.naming.CommunicationException; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.SearchControls; +import javax.naming.ldap.InitialLdapContext; +import java.util.Hashtable; public class LdapConnectionFactory extends BasePooledObjectFactory { diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java index ab3ded5..a2e5e0f 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java @@ -19,20 +19,15 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.ldap; -import java.io.IOException; -import java.net.InetAddress; -import java.net.Socket; -import java.net.UnknownHostException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - import javax.net.SocketFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.security.*; public class LdapSslSocketFactory extends SSLSocketFactory { @@ -71,14 +66,13 @@ public Socket createSocket(Socket socket, String s, int i, boolean b) } @Override - public Socket createSocket(String s, int i) throws IOException, - UnknownHostException { + public Socket createSocket(String s, int i) throws IOException { return context.getSocketFactory().createSocket(s, i); } @Override public Socket createSocket(String s, int i, InetAddress inetAddress, int i2) - throws IOException, UnknownHostException { + throws IOException { return context.getSocketFactory().createSocket(s, i, inetAddress, i2); } diff --git a/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java index 25ffb50..382fdf5 100644 --- a/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java @@ -19,12 +19,13 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.local; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; - +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.*; +import net.identio.server.service.authentication.AuthenticationProvider; +import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.*; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.transaction.model.TransactionData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -34,18 +35,11 @@ License, or (at your option) any later version. import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.LocalAuthMethod; -import net.identio.server.model.TransactionData; -import net.identio.server.model.UserPasswordAuthentication; -import net.identio.server.service.authentication.AuthenticationProvider; -import net.identio.server.service.authentication.AuthenticationService; -import net.identio.server.service.configuration.ConfigurationService; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; @Service @Scope("singleton") @@ -107,7 +101,7 @@ public LocalAuthenticationProvider(ConfigurationService configurationService, } public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + TransactionData transactionData) { LocalAuthMethod fileAuthMethod = (LocalAuthMethod) authMethod; UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; @@ -118,7 +112,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (userId == null || password == null) { LOG.error("UserId or password is empty"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } User user = globalUsersMap.get(fileAuthMethod).get(userId); @@ -126,7 +120,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (user == null) { LOG.error("Unknown user: {}", userPwAuthentication.getUserId()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } String hashedPassword = user.getPassword(); @@ -145,7 +139,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe LOG.info("Failed authentication for user {} with {} method", user.getUserId(), fileAuthMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } private void register(List authMethods, AuthenticationService authenticationService) { diff --git a/src/main/java/net/identio/server/service/authentication/model/Authentication.java b/src/main/java/net/identio/server/service/authentication/model/Authentication.java new file mode 100644 index 0000000..3312dfc --- /dev/null +++ b/src/main/java/net/identio/server/service/authentication/model/Authentication.java @@ -0,0 +1,25 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.authentication.model; + +public interface Authentication { + +} diff --git a/src/main/java/net/identio/server/service/authentication/model/AuthenticationErrorStatus.java b/src/main/java/net/identio/server/service/authentication/model/AuthenticationErrorStatus.java new file mode 100644 index 0000000..7fa3806 --- /dev/null +++ b/src/main/java/net/identio/server/service/authentication/model/AuthenticationErrorStatus.java @@ -0,0 +1,31 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.authentication.model; + +public class AuthenticationErrorStatus { + + public static final String INVALID_CREDENTIALS = "invalid.credentials"; + public static final String TECHNICAL_ERROR = "technical.error"; + public static final String USER_NOT_UNIQUE = "user.not.unique"; + public static final String AUTH_SAML_REJECTED = "auth.saml.rejected"; + public static final String AUTH_SAML_INVALID_RESPONSE = "auth.saml.invalid.response"; +} diff --git a/src/main/java/net/identio/server/model/AuthenticationResult.java b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java similarity index 56% rename from src/main/java/net/identio/server/model/AuthenticationResult.java rename to src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java index 4f0dcf4..dea4998 100644 --- a/src/main/java/net/identio/server/model/AuthenticationResult.java +++ b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java @@ -1,28 +1,32 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model; +package net.identio.server.service.authentication.model; + +import net.identio.server.model.AuthLevel; +import net.identio.server.model.AuthMethod; public class AuthenticationResult { private AuthenticationResultStatus status; - private ErrorStatus errorStatus; + private String errorStatus; private String challengeType; private String challengeValue; private String userId; @@ -38,11 +42,11 @@ public AuthenticationResult setStatus(AuthenticationResultStatus status) { return this; } - public ErrorStatus getErrorStatus() { + public String getErrorStatus() { return errorStatus; } - public AuthenticationResult setErrorStatus(ErrorStatus errorStatus) { + public AuthenticationResult setErrorStatus(String errorStatus) { this.errorStatus = errorStatus; return this; } diff --git a/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java new file mode 100644 index 0000000..872fab3 --- /dev/null +++ b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java @@ -0,0 +1,25 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.authentication.model; + +public enum AuthenticationResultStatus { + SUCCESS, FAIL, CHALLENGE +} diff --git a/src/main/java/net/identio/server/model/UserPasswordAuthentication.java b/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java similarity index 51% rename from src/main/java/net/identio/server/model/UserPasswordAuthentication.java rename to src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java index 616f8c4..c1dbcc8 100644 --- a/src/main/java/net/identio/server/model/UserPasswordAuthentication.java +++ b/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java @@ -1,23 +1,24 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model; +package net.identio.server.service.authentication.model; public class UserPasswordAuthentication implements Authentication { diff --git a/src/main/java/net/identio/server/model/X509Authentication.java b/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java similarity index 51% rename from src/main/java/net/identio/server/model/X509Authentication.java rename to src/main/java/net/identio/server/service/authentication/model/X509Authentication.java index ce1afe0..f79364b 100644 --- a/src/main/java/net/identio/server/model/X509Authentication.java +++ b/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java @@ -1,23 +1,24 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model; +package net.identio.server.service.authentication.model; import java.security.cert.X509Certificate; diff --git a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java index 5059cd1..6441cf2 100644 --- a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java @@ -19,31 +19,13 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.radius; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.zip.DataFormatException; - -import org.apache.xml.security.exceptions.Base64DecodingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Service; - import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.RadiusAuthMethod; -import net.identio.server.model.TransactionData; -import net.identio.server.model.UserPasswordAuthentication; +import net.identio.server.model.*; import net.identio.server.service.authentication.AuthenticationProvider; import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.*; import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.transaction.model.TransactionData; import net.identio.server.utils.DecodeUtils; import net.sourceforge.jradiusclient.RadiusAttribute; import net.sourceforge.jradiusclient.RadiusAttributeValues; @@ -52,6 +34,18 @@ License, or (at your option) any later version. import net.sourceforge.jradiusclient.exception.InvalidParameterException; import net.sourceforge.jradiusclient.exception.RadiusException; import net.sourceforge.jradiusclient.packets.PapAccessRequest; +import org.apache.xml.security.exceptions.Base64DecodingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.zip.DataFormatException; @Service @Scope("singleton") @@ -65,7 +59,7 @@ public class RadiusAuthenticationProvider implements AuthenticationProvider { @Autowired public RadiusAuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) throws InitializationException { + AuthenticationService authenticationService) { List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() .getRadiusAuthMethods(); @@ -89,7 +83,7 @@ public RadiusAuthenticationProvider(ConfigurationService configurationService, } public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + TransactionData transactionData) { RadiusAuthMethod radiusAuthMethod = (RadiusAuthMethod) authMethod; UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; @@ -117,13 +111,13 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe } catch (RadiusException ex) { LOG.error("An error occurend when authenticating user"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_TECHNICAL_ERROR); + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); } } } private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, String userId, String password, - String challenge) throws RadiusException { + String challenge) throws RadiusException { try { @@ -131,9 +125,7 @@ private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, Str radiusAuthMethod.getAuthPort(), radiusAuthMethod.getAccountPort(), radiusAuthMethod.getSharedSecret(), radiusAuthMethod.getTimeout()); - RadiusPacket accessRequest = null; - - accessRequest = new PapAccessRequest(userId, password); + RadiusPacket accessRequest = new PapAccessRequest(userId, password); if (challenge != null) { accessRequest.setAttribute(deserializeAttribute(challenge)); @@ -196,7 +188,7 @@ private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, Str LOG.error("Authentication failed for user {} with {}", userId, radiusAuthMethod.getName()); } new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } } catch (InvalidParameterException | IOException | Base64DecodingException | DataFormatException ex) { @@ -205,7 +197,7 @@ private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, Str } return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_TECHNICAL_ERROR); + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); } private RadiusAttribute deserializeAttribute(String data) diff --git a/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java index dd1e258..daae1e1 100644 --- a/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java @@ -19,55 +19,37 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.saml; -import java.io.File; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.zip.DataFormatException; - -import org.apache.xml.security.exceptions.Base64DecodingException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import net.identio.saml.Assertion; -import net.identio.saml.AuthentResponse; -import net.identio.saml.AuthentResponseBuilder; -import net.identio.saml.Endpoint; -import net.identio.saml.IdpSsoDescriptor; -import net.identio.saml.Metadata; -import net.identio.saml.MetadataBuilder; -import net.identio.saml.SamlConstants; -import net.identio.saml.Validator; -import net.identio.saml.exceptions.InvalidAssertionException; -import net.identio.saml.exceptions.InvalidAuthentResponseException; -import net.identio.saml.exceptions.InvalidSignatureException; -import net.identio.saml.exceptions.TechnicalException; -import net.identio.saml.exceptions.UnsignedSAMLObjectException; -import net.identio.saml.exceptions.UntrustedSignerException; +import net.identio.saml.*; +import net.identio.saml.exceptions.*; import net.identio.server.exceptions.InitializationException; import net.identio.server.exceptions.SamlException; -import net.identio.server.model.AuthLevel; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.IdentioConfiguration; -import net.identio.server.model.SamlAuthMethod; -import net.identio.server.model.SamlAuthRequestGenerationResult; -import net.identio.server.model.SamlAuthentication; -import net.identio.server.model.TransactionData; +import net.identio.server.model.*; import net.identio.server.service.authentication.AuthenticationProvider; import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.Authentication; +import net.identio.server.service.authentication.model.AuthenticationResult; +import net.identio.server.service.authentication.model.AuthenticationResultStatus; +import net.identio.server.service.authentication.model.AuthenticationErrorStatus; import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.orchestration.model.SamlAuthRequestGenerationResult; import net.identio.server.service.saml.MetadataService; import net.identio.server.service.saml.SamlService; +import net.identio.server.service.transaction.model.TransactionData; import net.identio.server.utils.DecodeUtils; +import org.apache.xml.security.exceptions.Base64DecodingException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.zip.DataFormatException; @Service public class SamlAuthenticationProvider implements AuthenticationProvider { @@ -100,14 +82,12 @@ public SamlAuthenticationProvider(ConfigurationService configurationService, register(configurationService.getConfiguration().getAuthMethodConfiguration().getSamlAuthMethods(), authenticationService); - } catch (TechnicalException | UnsignedSAMLObjectException | UntrustedSignerException - | InvalidSignatureException ex) { + } catch (TechnicalException ex) { throw new InitializationException("Could not initialize Metadata service", ex); } } - private void initRemoteIdpMetadata() throws TechnicalException, UnsignedSAMLObjectException, - UntrustedSignerException, InvalidSignatureException { + private void initRemoteIdpMetadata() throws TechnicalException { IdentioConfiguration config = configurationService.getConfiguration(); @@ -141,7 +121,7 @@ private void initRemoteIdpMetadata() throws TechnicalException, UnsignedSAMLObje } public SamlAuthRequestGenerationResult initRequest(SamlAuthMethod authMethod, ArrayList targetAuthLevels, - String transactionId) throws SamlException { + String transactionId) throws SamlException { Metadata remoteMetadata = remoteIdpMetadatasByName.get(authMethod.getName()); @@ -165,7 +145,7 @@ public SamlAuthRequestGenerationResult initRequest(SamlAuthMethod authMethod, Ar } public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + TransactionData transactionData) { LOG.info("Validating SAML response from proxy IDP"); @@ -189,21 +169,21 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (!SamlConstants.STATUS_SUCCESS.equals(responseStatusCode)) { LOG.error("* Authentication rejected by proxy IDP"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_REJECTED_BY_PROXY); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_REJECTED); } // Verify the presence of a SAML Assertion if (assertion == null) { LOG.error("* No assertion found in response"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_NO_ASSERTION_IN_RESPONSE); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // Check inResponseTo attribute coherence if (!transactionData.getSamlProxyRequestId().equals(assertion.getInResponseTo())) { LOG.error("* InResponseTo ID doesn't match request ID"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_INVALID_INRESPONSETO); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // Check that the response user ID matches the ID in session @@ -211,7 +191,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe || !assertion.getSubjectNameID().equals(transactionData.getUserSession().getUserId())) { LOG.error("* Audience in assertion doesn't match IDP EntityID"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_USER_ID_MISMATCH); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // Check that the recipient of the assertion is the IDP @@ -219,7 +199,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe || !assertion.getAudienceRestriction().equals(idpMetadata.getEntityID())) { LOG.error("* Audience in assertion doesn't match IDP EntityID"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_WRONG_AUDIENCE); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // Check recipient and destination @@ -230,14 +210,14 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (recipient == null) { LOG.error("* No recipient specified in assertion"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_NO_RECIPIENT); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } if (destination == null) { LOG.error("* No destination specified in response"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_NO_DESTINATION); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } for (Endpoint endpoint : idpMetadata.getSpSsoDescriptors().get(0).getAssertionConsumerServices()) { @@ -251,7 +231,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe if (!validation) { LOG.error("* Recipient or destination in response doesn't match an IDP endpoint"); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_WRONG_RECIPIENT_OR_DESTINATION); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // Check assertion time conditions @@ -260,11 +240,9 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe } catch (InvalidAssertionException ex) { LOG.error("* Conditions in the assertion are not valid: {}", ex.getMessage()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_CONDITIONS_NOT_MET); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } - validation = false; - try { validation = remoteValidator.validate(response); @@ -275,7 +253,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe LOG.debug("* Detailed stacktrace:", ex); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_SAML_INVALID_RESPONSE); + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); } // If the assertion is valid @@ -293,7 +271,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe LOG.error("* Error when parsing SAML Response: {}", ex.getMessage()); } return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_TECHNICAL_ERROR); + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); } private void register(List authMethods, AuthenticationService authenticationService) { diff --git a/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java index 267752b..1ed72d7 100644 --- a/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java @@ -19,15 +19,15 @@ License, or (at your option) any later version. */ package net.identio.server.service.authentication.x509; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - +import net.identio.server.exceptions.ConfigurationException; +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.*; +import net.identio.server.service.authentication.AuthenticationProvider; +import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.*; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.utils.SecurityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -40,20 +40,14 @@ License, or (at your option) any later version. import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.stereotype.Service; -import net.identio.server.exceptions.ConfigurationException; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.TransactionData; -import net.identio.server.model.X509AuthMethod; -import net.identio.server.model.X509Authentication; -import net.identio.server.service.authentication.AuthenticationProvider; -import net.identio.server.service.authentication.AuthenticationService; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.SecurityUtils; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; @Service @Scope("singleton") @@ -135,7 +129,7 @@ private void cacheCertificates(X509AuthMethod authMethod) throws InitializationE } public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + TransactionData transactionData) { X509AuthMethod x509AuthMethod = (X509AuthMethod) authMethod; X509Authentication x509Authentication = (X509Authentication) authentication; @@ -153,7 +147,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe authMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } // Check expressions @@ -183,7 +177,7 @@ public AuthenticationResult validate(AuthMethod authMethod, Authentication authe LOG.info("Could not validate user certificate with method {}", authMethod.getName()); return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(ErrorStatus.AUTH_INVALID_CREDENTIALS); + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); } private void register(List authMethods, AuthenticationService authenticationService) { diff --git a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java index 6bb46b7..ee88256 100644 --- a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java +++ b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java @@ -19,19 +19,18 @@ License, or (at your option) any later version. */ package net.identio.server.service.authorization; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - +import net.identio.server.model.AuthorizationScope; +import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; +import net.identio.server.service.authorization.exceptions.UnknownScopeException; +import net.identio.server.service.configuration.ConfigurationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import net.identio.server.model.AuthorizationScope; -import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; -import net.identio.server.service.authorization.exceptions.UnknownScopeException; -import net.identio.server.service.configuration.ConfigurationService; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; @Service public class AuthorizationService { diff --git a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java index f1413c4..dc8e4fb 100644 --- a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java +++ b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java @@ -19,36 +19,26 @@ License, or (at your option) any later version. */ package net.identio.server.service.authpolicy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - +import net.identio.saml.SamlConstants; +import net.identio.server.exceptions.AuthMethodNotAllowedException; +import net.identio.server.exceptions.UnknownAuthLevelException; +import net.identio.server.exceptions.UnknownAuthMethodException; +import net.identio.server.model.*; +import net.identio.server.service.authentication.model.AuthenticationResult; +import net.identio.server.service.authpolicy.model.AuthPolicyDecision; +import net.identio.server.service.authpolicy.model.AuthPolicyDecisionStatus; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.orchestration.model.RequestParsingInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import net.identio.saml.SamlConstants; -import net.identio.server.exceptions.AuthMethodNotAllowedException; -import net.identio.server.exceptions.UnknownAuthLevelException; -import net.identio.server.exceptions.UnknownAuthMethodException; -import net.identio.server.model.AppAuthLevel; -import net.identio.server.model.AuthLevel; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.AuthMethodConfiguration; -import net.identio.server.model.AuthPolicyConfiguration; -import net.identio.server.model.AuthPolicyDecision; -import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.AuthSession; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.SamlAuthMethod; -import net.identio.server.model.State; -import net.identio.server.model.StepUpAuthMethod; -import net.identio.server.model.UserSession; -import net.identio.server.service.configuration.ConfigurationService; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; @Service @Scope("singleton") @@ -59,7 +49,7 @@ public class AuthPolicyService { private AuthPolicyConfiguration authPolicyConfiguration; private AuthMethodConfiguration authMethodConfiguration; - private HashMap authLevelByUrn = new HashMap<>();; + private HashMap authLevelByUrn = new HashMap<>(); private HashMap authLevelByApp = new HashMap<>(); private HashMap authMethodByName = new HashMap<>(); @@ -95,7 +85,7 @@ public AuthPolicyService(ConfigurationService configurationService) { } - public ArrayList determineTargetAuthLevel(AuthRequestValidationResult arValidationResult) { + public ArrayList determineTargetAuthLevel(RequestParsingInfo parsingInfo) { LOG.debug("Determining authentication strategy for request"); @@ -106,21 +96,21 @@ public ArrayList determineTargetAuthLevel(AuthRequestValidationResult // this application // If none is specified, we apply the default authent level List requestedAuthLevels = new ArrayList<>(); - String requestedComparison = null; + String requestedComparison; ArrayList targetAuthLevels = new ArrayList<>(); - if (arValidationResult.getRequestedAuthLevels() != null) { + if (parsingInfo.getRequestedAuthLevels() != null) { - requestedAuthLevels = arValidationResult.getRequestedAuthLevels(); - requestedComparison = arValidationResult.getAuthLevelComparison(); + requestedAuthLevels = parsingInfo.getRequestedAuthLevels(); + requestedComparison = parsingInfo.getAuthLevelComparison(); LOG.debug("* Request specify an auth level. Applying requested auth level"); } else { // Request doesn't specify a minimum auth level // , we check if we have a specific auth level // for this application - AppAuthLevel appAuthLevel = authLevelByApp.get(arValidationResult.getSourceApplicationName()); + AppAuthLevel appAuthLevel = authLevelByApp.get(parsingInfo.getSourceApplicationName()); if (appAuthLevel != null) { @@ -196,7 +186,7 @@ public HashSet determineTargetAuthMethods(ArrayList targe } public AuthPolicyDecision checkPreviousAuthSessions(UserSession userSession, - ArrayList targetAuthLevels) { + ArrayList targetAuthLevels) { LOG.debug("Check previous authentication sessions"); @@ -208,68 +198,41 @@ public AuthPolicyDecision checkPreviousAuthSessions(UserSession userSession, LOG.debug("* Found compliant auth session"); - return new AuthPolicyDecision(State.RESPONSE, authSession, null); + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) + .setValidatedAuthSession(authSession); } } } LOG.debug("* No compliant auth session found. Asking for an explicit authentication"); - return new AuthPolicyDecision(State.AUTH, null, null); + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); } - public void checkAllowedAuthMethods(State state, HashSet targetAuthMethods, - AuthMethod selectedAuthMethod, AuthMethod submittedAuthMethod) + public void checkAllowedAuthMethods(HashSet targetAuthMethods, AuthMethod submittedAuthMethod) throws UnknownAuthMethodException, AuthMethodNotAllowedException { if (submittedAuthMethod == null) { throw new UnknownAuthMethodException("Unknown authentication method"); } - // Check if the used authentication method is a valid step-up - // authentication method - switch (state) { - case AUTH: - if (!targetAuthMethods.contains(submittedAuthMethod)) { - throw new AuthMethodNotAllowedException("Authentication method " + submittedAuthMethod.getName() - + " is not allowed for this transaction"); - } - break; - - case STEP_UP_AUTHENTICATION: - if (!selectedAuthMethod.getStepUpAuthentication().getAuthMethod().equals(submittedAuthMethod)) { + if (!targetAuthMethods.contains(submittedAuthMethod)) { throw new AuthMethodNotAllowedException("Authentication method " + submittedAuthMethod.getName() + " is not allowed for this transaction"); - } - default: } } public AuthPolicyDecision checkAuthPolicyCompliance(UserSession userSession, AuthenticationResult result, - ArrayList targetAuthLevels, AuthMethod selectedAuthMethod, State state) { - - if (state == State.STEP_UP_AUTHENTICATION) { - - AuthSession authSession = updateUserSession(userSession, result, - selectedAuthMethod.getStepUpAuthentication(), - selectedAuthMethod.getStepUpAuthentication().getAuthLevel()); - return new AuthPolicyDecision(State.RESPONSE, authSession, null); - } - - if (result.getAuthMethod().getStepUpAuthentication() != null) { + ArrayList targetAuthLevels) { - LOG.debug("* This method has a step-up authentication declared"); + // Check that the authlevel matches + if (targetAuthLevels.contains(result.getAuthLevel())) { - return new AuthPolicyDecision(State.STEP_UP_AUTHENTICATION, null, - new HashSet(Arrays.asList(result.getAuthMethod()))); + AuthSession authSession = updateUserSession(userSession, result, result.getAuthLevel()); + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) + .setValidatedAuthSession(authSession); } else { - // Check that the authlevel matches - if (targetAuthLevels.contains(result.getAuthLevel())) { - AuthSession authSession = updateUserSession(userSession, result, null, result.getAuthLevel()); - return new AuthPolicyDecision(State.RESPONSE, authSession, null); - } else { - return new AuthPolicyDecision(state, null, null); - } + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); } } @@ -306,7 +269,8 @@ public String getLogo(String authMethodName) { } private AuthSession updateUserSession(UserSession userSession, AuthenticationResult result, - StepUpAuthMethod stepupAuthMethod, AuthLevel authLevel) { - return userSession.addAuthSession(result.getUserId(), result.getAuthMethod(), stepupAuthMethod, authLevel); + AuthLevel authLevel) { + + return userSession.addAuthSession(result.getUserId(), result.getAuthMethod(), authLevel); } } diff --git a/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java new file mode 100644 index 0000000..3db1c6d --- /dev/null +++ b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java @@ -0,0 +1,61 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.authpolicy.model; + +import net.identio.server.model.AuthMethod; +import net.identio.server.model.AuthSession; + +import java.util.HashSet; + +public class AuthPolicyDecision { + + private AuthPolicyDecisionStatus status; + private AuthSession validatedAuthSession; + private HashSet nextAuthMethods; + + public AuthPolicyDecisionStatus getStatus() { + return status; + } + + public AuthPolicyDecision setStatus(AuthPolicyDecisionStatus status) { + this.status = status; + return this; + } + + public AuthSession getValidatedAuthSession() { + return validatedAuthSession; + } + + public AuthPolicyDecision setValidatedAuthSession(AuthSession validatedAuthSession) { + this.validatedAuthSession = validatedAuthSession; + return this; + } + + public HashSet getNextAuthMethods() { + return nextAuthMethods; + } + + public AuthPolicyDecision setNextAuthMethods(HashSet nextAuthMethods) { + this.nextAuthMethods = nextAuthMethods; + return this; + } + +} diff --git a/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecisionStatus.java b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecisionStatus.java new file mode 100644 index 0000000..374f2f2 --- /dev/null +++ b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecisionStatus.java @@ -0,0 +1,26 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.authpolicy.model; + +public enum AuthPolicyDecisionStatus { + OK, STEP_UP, AUTH +} diff --git a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java index 11a30e1..2c247a9 100644 --- a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java +++ b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java @@ -19,11 +19,8 @@ License, or (at your option) any later version. */ package net.identio.server.service.configuration; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.nio.file.Paths; - +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.IdentioConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -32,8 +29,10 @@ License, or (at your option) any later version. import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.IdentioConfiguration; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Paths; @Service public class ConfigurationService { @@ -81,7 +80,7 @@ public IdentioConfiguration getConfiguration() { return configuration; } - private void setDefaultValues() throws IOException { + private void setDefaultValues() { String configDirectoryPath = Paths.get(configFile).getParent().toAbsolutePath().normalize().toString(); String home = Paths.get(configDirectoryPath).getParent().toString(); diff --git a/src/main/java/net/identio/server/service/oauth/ConsentService.java b/src/main/java/net/identio/server/service/oauth/ConsentService.java new file mode 100644 index 0000000..4a6a511 --- /dev/null +++ b/src/main/java/net/identio/server/service/oauth/ConsentService.java @@ -0,0 +1,62 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.oauth; + +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.model.AuthorizationScope; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.mvc.oauth.model.ConsentContext; +import net.identio.server.service.transaction.TransactionService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class ConsentService { + + private static final Logger LOG = LoggerFactory.getLogger(ConsentService.class); + + @Autowired + private TransactionService transactionService; + + public ConsentContext getConsentContext(String transactionId, String sessionId) + throws WebSecurityException { + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + List authorizedScopes = transactionData + .getRequestParsingInfo() + .getRequestedScopes().stream() + .map(AuthorizationScope::getPublicCopy) + .collect(Collectors.toList()); + + return new ConsentContext().setRequestedScopes(authorizedScopes) + .setAudience(transactionData.getRequestParsingInfo().getSourceApplicationName()) + .setAudienceLogo(""); + + } +} diff --git a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java index 5c7d660..cdd4daf 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java @@ -1,6 +1,6 @@ package net.identio.server.service.oauth; -import net.identio.server.model.OAuthClient; +import net.identio.server.service.oauth.model.OAuthClient; public interface OAuthClientRepository { diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index c6d6717..2caa02a 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -19,6 +19,28 @@ License, or (at your option) any later version. */ package net.identio.server.service.oauth; +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.*; +import net.identio.server.service.authorization.AuthorizationService; +import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; +import net.identio.server.service.authorization.exceptions.UnknownScopeException; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.oauth.model.OAuthClient; +import net.identio.server.service.oauth.model.OAuthErrors; +import net.identio.server.service.oauth.model.OAuthGrants; +import net.identio.server.service.oauth.model.OAuthResponseType; +import net.identio.server.service.orchestration.model.RequestParsingInfo; +import net.identio.server.service.orchestration.model.RequestParsingStatus; +import net.identio.server.service.orchestration.model.ResponseData; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + import java.io.FileInputStream; import java.io.IOException; import java.security.KeyStore; @@ -31,31 +53,6 @@ License, or (at your option) any later version. import java.util.List; import java.util.UUID; -import net.identio.server.service.oauth.model.OAuthErrors; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import com.auth0.jwt.JWT; -import com.auth0.jwt.algorithms.Algorithm; - -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.OAuthClient; -import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.model.ProtocolType; -import net.identio.server.model.AuthorizationScope; -import net.identio.server.model.UserSession; -import net.identio.server.service.authorization.AuthorizationService; -import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; -import net.identio.server.service.authorization.exceptions.UnknownScopeException; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.oauth.model.OAuthGrants; -import net.identio.server.service.oauth.model.OAuthResponseType; - @Service public class OAuthService { @@ -63,6 +60,7 @@ public class OAuthService { @Autowired private OAuthClientRepository clientRepository; + @Autowired private AuthorizationService authorizationService; @@ -101,9 +99,9 @@ public OAuthService(ConfigurationService configurationService) throws Initializa } } - public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest request) { + public RequestParsingInfo validateAuthentRequest(OAuthInboundRequest request) { - AuthRequestValidationResult result = new AuthRequestValidationResult(); + RequestParsingInfo result = new RequestParsingInfo(); result.setProtocolType(ProtocolType.OAUTH); @@ -115,7 +113,7 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re // Fetch client OAuthClient client = clientRepository.getOAuthClientbyId(request.getClientId()); if (client == null) { - return result.setSuccess(false).setErrorStatus(OAuthErrors.UNKNOWN_CLIENT); + return result.setStatus(RequestParsingStatus.FATAL_ERROR).setErrorStatus(OAuthErrors.UNKNOWN_CLIENT); } // Verify redirectUri @@ -125,13 +123,13 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re if (checkRedirectUri(client, request.getRedirectUri())) { redirectUri = request.getRedirectUri(); } else { - return result.setSuccess(false).setErrorStatus(OAuthErrors.UNKNOWN_REDIRECT_URI); + return result.setStatus(RequestParsingStatus.FATAL_ERROR).setErrorStatus(OAuthErrors.UNKNOWN_REDIRECT_URI); } } // Validate response type value if (request.getResponseType() == null || !checkValidResponseTypes(request.getResponseType())) { - return result.setSuccess(false).setErrorStatus(OAuthErrors.RESPONSE_TYPE_NOT_SUPPORTED) + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(OAuthErrors.RESPONSE_TYPE_NOT_SUPPORTED) .setResponseUrl(redirectUri); } @@ -140,22 +138,22 @@ public AuthRequestValidationResult validateAuthentRequest(OAuthInboundRequest re try { scopes = authorizationService.getScopes(request.getScopes()); } catch (UnknownScopeException | NoScopeProvidedException e) { - return result.setSuccess(false).setErrorStatus(OAuthErrors.INVALID_SCOPE).setResponseUrl(redirectUri); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(OAuthErrors.INVALID_SCOPE).setResponseUrl(redirectUri); } // Validate client authorization regarding allowed scopes and response // types if (!checkClientAuthorization(client, request.getResponseType(), request.getScopes())) { - return result.setSuccess(false).setErrorStatus(OAuthErrors.UNAUTHORIZED_CLIENT).setResponseUrl(redirectUri); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(OAuthErrors.UNAUTHORIZED_CLIENT).setResponseUrl(redirectUri); } - result.setSuccess(true).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) + result.setStatus(RequestParsingStatus.OK).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) .setRequestedScopes(scopes).setResponseType(request.getResponseType()); return result; } - public String generateSuccessResponse(AuthRequestValidationResult result, UserSession userSession) { + public ResponseData generateSuccessResponse(RequestParsingInfo result, UserSession userSession) { StringBuilder responseBuilder = new StringBuilder(); @@ -200,10 +198,10 @@ public String generateSuccessResponse(AuthRequestValidationResult result, UserSe responseBuilder.append("&state=").append(result.getRelayState()); } - return responseBuilder.toString(); + return new ResponseData().setUrl(responseBuilder.toString()); } - public String generateErrorResponse(AuthRequestValidationResult result) { + public ResponseData generateErrorResponse(RequestParsingInfo result) { StringBuilder responseBuilder = new StringBuilder(); @@ -213,7 +211,7 @@ public String generateErrorResponse(AuthRequestValidationResult result) { responseBuilder.append("&state=").append(result.getRelayState()); } - return responseBuilder.toString(); + return new ResponseData().setUrl(responseBuilder.toString()); } private boolean checkValidResponseTypes(String responseType) { diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java index 81a95a2..e21cb0c 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -1,10 +1,9 @@ package net.identio.server.service.oauth.infrastructure; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.HashMap; - +import net.identio.server.exceptions.InitializationException; +import net.identio.server.service.oauth.model.OAuthClient; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.oauth.OAuthClientRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -12,10 +11,10 @@ import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.OAuthClient; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.service.oauth.OAuthClientRepository; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashMap; @Service public class FileOAuthClientRepository implements OAuthClientRepository { diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java index 0808511..699485a 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java @@ -1,8 +1,8 @@ package net.identio.server.service.oauth.infrastructure; -import java.util.List; +import net.identio.server.service.oauth.model.OAuthClient; -import net.identio.server.model.OAuthClient; +import java.util.List; public class OAuthClientFile { diff --git a/src/main/java/net/identio/server/model/OAuthClient.java b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java similarity index 53% rename from src/main/java/net/identio/server/model/OAuthClient.java rename to src/main/java/net/identio/server/service/oauth/model/OAuthClient.java index feaf47c..50084c0 100644 --- a/src/main/java/net/identio/server/model/OAuthClient.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java @@ -1,23 +1,24 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model; +package net.identio.server.service.oauth.model; import java.util.List; @@ -29,7 +30,9 @@ public class OAuthClient { private List allowedScopes; private List responseUri; private List allowedGrants; - + + private boolean needConsent; + public String getName() { return name; } @@ -77,4 +80,12 @@ public List getAllowedGrants() { public void setAllowedGrants(List allowedGrants) { this.allowedGrants = allowedGrants; } + + public boolean isNeedConsent() { + return needConsent; + } + + public void setNeedConsent(boolean needConsent) { + this.needConsent = needConsent; + } } diff --git a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java new file mode 100644 index 0000000..996a2c6 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java @@ -0,0 +1,217 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration; + +import net.identio.server.exceptions.*; +import net.identio.server.model.*; +import net.identio.server.service.authentication.AuthenticationService; +import net.identio.server.service.authentication.model.Authentication; +import net.identio.server.service.authentication.model.AuthenticationResult; +import net.identio.server.service.authentication.model.AuthenticationResultStatus; +import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; +import net.identio.server.service.authpolicy.AuthPolicyService; +import net.identio.server.service.authpolicy.model.AuthPolicyDecision; +import net.identio.server.service.authpolicy.model.AuthPolicyDecisionStatus; +import net.identio.server.service.oauth.OAuthService; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.service.saml.SamlService; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.service.transaction.TransactionService; +import net.identio.server.service.transaction.model.TransactionState; +import net.identio.server.service.usersession.UserSessionService; +import net.identio.server.service.orchestration.model.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class AuthOrchestrationService { + + private static final Logger LOG = LoggerFactory.getLogger(AuthOrchestrationService.class); + + @Autowired + private UserSessionService userSessionService; + + @Autowired + private SamlService samlService; + + @Autowired + private OAuthService oauthService; + + @Autowired + private AuthPolicyService authPolicyService; + + @Autowired + private TransactionService transactionService; + + @Autowired + private AuthenticationService authenticationService; + + @Autowired + private SamlAuthenticationProvider samlAuthenticationProvider; + + public AuthenticationValidationResult handleTransparentAuthentication(Authentication authentication, String sessionId, + String transactionId) + throws WebSecurityException, ServerException { + + LOG.debug("Check for transparent authentication"); + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + UserSession userSession = transactionData.getUserSession(); + + AuthenticationResult result = authenticationService.validateTransparent(authentication, transactionData); + + if (result != null && result.getStatus() == AuthenticationResultStatus.SUCCESS) { + + AuthPolicyDecision decision = authPolicyService.checkAuthPolicyCompliance(userSession, result, + transactionData.getTargetAuthLevels()); + + if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { + + try { + + return new AuthenticationValidationResult().setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateSuccessResponse(decision, + transactionData.getRequestParsingInfo(), userSession)); + + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } finally { + transactionService.removeTransactionData(transactionData); + } + } + } + + return new AuthenticationValidationResult().setValidationStatus(ValidationStatus.AUTH); + } + + public AuthenticationValidationResult handleExplicitAuthentication(String transactionId, String sessionId, + String authMethodName, Authentication authentication) + throws WebSecurityException, ValidationException, ServerException { + + LOG.debug("Validating explicit authentication: {}", authMethodName); + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + // Check that we are in the correct transaction state + if (transactionData.getState() != TransactionState.AUTH) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); + } + + AuthenticationValidationResult validationResult = new AuthenticationValidationResult(); + validationResult.setProtocolType(transactionData.getProtocolType()); + + // Try to map the auth method name to a known method + AuthMethod authMethod = null; + + try { + + authMethod = authMethodName != null ? + authPolicyService.getAuthMethodByName(authMethodName) : transactionData.getSelectedAuthMethod(); + + authPolicyService.checkAllowedAuthMethods(transactionData.getTargetAuthMethods(), authMethod); + + } catch (UnknownAuthMethodException e) { + transactionService.removeTransactionData(transactionData); + throw new ValidationException(OrchestrationErrorStatus.AUTH_METHOD_UNKNOWN); + } catch (AuthMethodNotAllowedException e) { + transactionService.removeTransactionData(transactionData); + throw new ValidationException(OrchestrationErrorStatus.AUTH_METHOD_NOT_ALLOWED); + } + + AuthenticationResult authResult = authenticationService.validateExplicit(authMethod, authentication, + transactionData); + + switch (authResult.getStatus()) { + + case SUCCESS: + + AuthPolicyDecision decision = authPolicyService.checkAuthPolicyCompliance( + transactionData.getUserSession(), authResult, transactionData.getTargetAuthLevels()); + + if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { + + try { + validationResult.setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateSuccessResponse( + decision, + transactionData.getRequestParsingInfo(), + transactionData.getUserSession())); + + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } + finally { + transactionService.removeTransactionData(transactionData); + } + } + break; + + case FAIL: + validationResult.setValidationStatus(ValidationStatus.ERROR) + .setErrorStatus(authResult.getErrorStatus()); + validationResult.setErrorStatus(authResult.getErrorStatus()); + break; + + case CHALLENGE: + validationResult.setValidationStatus(ValidationStatus.CHALLENGE); + validationResult.setChallengeType(authResult.getChallengeType()); + validationResult.setChallengeValue(authResult.getChallengeValue()); + break; + } + + return validationResult; + } + + public List getAuthMethods(String transactionId, String sessionId) throws WebSecurityException { + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + // Check that we are in the correct transaction state + if (transactionData.getState() != TransactionState.AUTH) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); + } + + return transactionData.getTargetAuthMethods().stream().filter(AuthMethod::isExplicit) + .sorted(Comparator.comparing(AuthMethod::getName)).collect(Collectors.toList()); + + } + + private ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo parsingInfo, + UserSession userSession) throws SamlException { + + if (parsingInfo.getProtocolType() == ProtocolType.SAML) { + return samlService.generateSuccessResponse(decision, parsingInfo, userSession); + } else { + return oauthService.generateSuccessResponse(parsingInfo, userSession); + } + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java new file mode 100644 index 0000000..784d6ec --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java @@ -0,0 +1,93 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration; + +import net.identio.server.exceptions.*; +import net.identio.server.model.AuthMethod; +import net.identio.server.model.SamlAuthMethod; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.service.orchestration.model.SamlAuthRequestGenerationResult; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; +import net.identio.server.service.authpolicy.AuthPolicyService; +import net.identio.server.service.transaction.TransactionService; +import net.identio.server.service.orchestration.model.OrchestrationErrorStatus; +import net.identio.server.service.transaction.model.TransactionState; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ProxyAuthOrchestrationService { + + private static final Logger LOG = LoggerFactory.getLogger(ProxyAuthOrchestrationService.class); + + @Autowired + private AuthPolicyService authPolicyService; + + @Autowired + private TransactionService transactionService; + + @Autowired + private SamlAuthenticationProvider samlAuthenticationProvider; + + public SamlAuthRequestGenerationResult initSamlRequest(String transactionId, String sessionId, + String authMethodName) + throws ValidationException, WebSecurityException, ServerException { + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + // Check that we are in the correct transaction state + if (transactionData.getState() != TransactionState.AUTH) { + + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); + } + + try { + AuthMethod authMethod = authPolicyService.getAuthMethodByName(authMethodName); + + transactionData.setSelectedAuthMethod(authMethod); + + authPolicyService.checkAllowedAuthMethods(transactionData.getTargetAuthMethods(), authMethod); + + SamlAuthRequestGenerationResult result = samlAuthenticationProvider.initRequest((SamlAuthMethod) authMethod, + transactionData.getTargetAuthLevels(), transactionId); + + transactionData.setSamlProxyRequestId(result.getRequestId()); + + return result; + + } catch (UnknownAuthMethodException e) { + throw new ValidationException(OrchestrationErrorStatus.AUTH_METHOD_UNKNOWN); + } catch (AuthMethodNotAllowedException e) { + throw new ValidationException(OrchestrationErrorStatus.AUTH_METHOD_NOT_ALLOWED); + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } finally { + transactionService.removeTransactionData(transactionData); + } + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java new file mode 100644 index 0000000..4daea4a --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java @@ -0,0 +1,159 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration; + +import net.identio.server.exceptions.SamlException; +import net.identio.server.service.orchestration.exceptions.ServerException; +import net.identio.server.model.*; +import net.identio.server.service.authpolicy.AuthPolicyService; +import net.identio.server.service.authpolicy.model.AuthPolicyDecision; +import net.identio.server.service.authpolicy.model.AuthPolicyDecisionStatus; +import net.identio.server.service.oauth.OAuthService; +import net.identio.server.service.orchestration.exceptions.ValidationException; +import net.identio.server.service.saml.SamlService; +import net.identio.server.service.transaction.model.TransactionData; +import net.identio.server.service.transaction.TransactionService; +import net.identio.server.service.transaction.model.TransactionState; +import net.identio.server.service.usersession.UserSessionService; +import net.identio.server.service.orchestration.model.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.HashSet; + +@Service +public class RequestOrchestrationService { + + private static final Logger LOG = LoggerFactory.getLogger(RequestOrchestrationService.class); + + @Autowired + private TransactionService transactionService; + + @Autowired + private SamlService samlService; + + @Autowired + private OAuthService oauthService; + + @Autowired + private UserSessionService userSessionService; + + @Autowired + private AuthPolicyService authPolicyService; + + public RequestValidationResult validateRequest(InboundRequest request, String sessionId) + throws ServerException, ValidationException { + + RequestValidationResult validationResult = new RequestValidationResult(); + + // Validate the request + RequestParsingInfo parsingInfo = parseRequest(request); + + switch (parsingInfo.getStatus()) { + + case FATAL_ERROR: + throw new ValidationException(parsingInfo.getErrorStatus()); + + case RESPONSE_ERROR: + try { + return validationResult.setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateErrorResponse(parsingInfo)); + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } + + } + + TransactionData transactionData = transactionService.createTransaction(); + UserSession userSession = userSessionService.getUserSession(sessionId); + transactionData.setUserSession(userSession); + transactionData.setProtocolType(parsingInfo.getProtocolType()); + + validationResult.setTransactionId(transactionData.getTransactionId()); + validationResult.setSessionId(userSession.getId()); + + // Determine target auth levels and auth methods + ArrayList targetAuthLevels = authPolicyService.determineTargetAuthLevel(parsingInfo); + HashSet targetAuthMethods = authPolicyService.determineTargetAuthMethods(targetAuthLevels); + + // Check if previous authentications match + AuthPolicyDecision decision = authPolicyService.checkPreviousAuthSessions(userSession, targetAuthLevels); + + if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { + + try { + + validationResult.setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateSuccessResponse(decision, parsingInfo, userSession)); + + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } finally { + transactionService.removeTransactionData(transactionData); + } + + + } else { + + validationResult.setValidationStatus(ValidationStatus.AUTH); + + // Save data that will need later in the transaction + transactionData.setState(TransactionState.AUTH); + transactionData.setRequestParsingInfo(parsingInfo); + transactionData.setTargetAuthLevels(targetAuthLevels); + transactionData.setTargetAuthMethods(targetAuthMethods); + } + + return validationResult; + } + + private RequestParsingInfo parseRequest(InboundRequest request) { + + if (request instanceof SamlInboundRequest) { + return samlService.validateAuthentRequest((SamlInboundRequest) request); + } else { + return oauthService.validateAuthentRequest((OAuthInboundRequest) request); + } + } + + private ResponseData generateErrorResponse(RequestParsingInfo parsingInfo) throws SamlException { + + if (parsingInfo.getProtocolType() == ProtocolType.SAML) { + return samlService.generateErrorResponse(parsingInfo); + } else { + return oauthService.generateErrorResponse(parsingInfo); + } + } + + private ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo parsingInfo, + UserSession userSession) throws SamlException { + + if (parsingInfo.getProtocolType() == ProtocolType.SAML) { + return samlService.generateSuccessResponse(decision, parsingInfo, userSession); + } else { + return oauthService.generateSuccessResponse(parsingInfo, userSession); + } + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java new file mode 100644 index 0000000..e141f33 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java @@ -0,0 +1,34 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.orchestration.exceptions; + +public class ServerException extends Exception { + + private static final long serialVersionUID = 3342749474880290649L; + + public ServerException(String s) { + super(s); + } + + public ServerException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java new file mode 100644 index 0000000..10d325b --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java @@ -0,0 +1,34 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.orchestration.exceptions; + +public class ValidationException extends Exception { + + private static final long serialVersionUID = 974071100448457158L; + + public ValidationException(String s) { + super(s); + } + + public ValidationException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java new file mode 100644 index 0000000..1f3b17e --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java @@ -0,0 +1,35 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration.exceptions; + +public class WebSecurityException extends Exception { + + private static final long serialVersionUID = -5444195629811859215L; + + public WebSecurityException(String s) { + super(s); + } + + public WebSecurityException(String s, Throwable e) { + super(s, e); + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/AuthenticationValidationResult.java b/src/main/java/net/identio/server/service/orchestration/model/AuthenticationValidationResult.java new file mode 100644 index 0000000..afed427 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/AuthenticationValidationResult.java @@ -0,0 +1,87 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.orchestration.model; + +import net.identio.server.model.ProtocolType; + +public class AuthenticationValidationResult { + + private ValidationStatus validationStatus; + private String errorStatus; + private ResponseData responseData; + private ProtocolType protocolType; + private String challengeType; + private String challengeValue; + + public ValidationStatus getValidationStatus() { + return validationStatus; + } + + public AuthenticationValidationResult setValidationStatus(ValidationStatus state) { + this.validationStatus = state; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public AuthenticationValidationResult setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public ResponseData getResponseData() { + return responseData; + } + + public AuthenticationValidationResult setResponseData(ResponseData responseData) { + this.responseData = responseData; + return this; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public AuthenticationValidationResult setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + return this; + } + + public String getChallengeType() { + return challengeType; + } + + public AuthenticationValidationResult setChallengeType(String challengeType) { + this.challengeType = challengeType; + return this; + } + + public String getChallengeValue() { + return challengeValue; + } + + public AuthenticationValidationResult setChallengeValue(String challengeValue) { + this.challengeValue = challengeValue; + return this; + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java new file mode 100644 index 0000000..bfc4fcb --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java @@ -0,0 +1,31 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration.model; + +public class OrchestrationErrorStatus { + + public static final String SERVER_ERROR = "server.error"; + public static final String AUTH_METHOD_UNKNOWN = "auth.method.unknown"; + public static final String AUTH_METHOD_NOT_ALLOWED = "auth.method.not.allowed"; + public static final String INVALID_TRANSACTION = "invalid.transaction"; + public static final String INVALID_REQUEST = "invalid.request"; +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java new file mode 100644 index 0000000..2bc2d57 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java @@ -0,0 +1,150 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.orchestration.model; + +import net.identio.server.model.AuthLevel; +import net.identio.server.model.AuthorizationScope; +import net.identio.server.model.ProtocolType; + +import java.util.List; + +public class RequestParsingInfo { + + private RequestParsingStatus status; + private String errorStatus; + private String requestId; + private ProtocolType protocolType; + private String sourceApplicationName; + private boolean forceAuthentication; + private String authLevelComparison; + private List requestedAuthLevels; + private String relayState; + private String responseUrl; + private List requestedScopes; + private String responseType; + + public RequestParsingStatus getStatus() { + return status; + } + + public RequestParsingInfo setStatus(RequestParsingStatus status) { + this.status = status; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public RequestParsingInfo setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public String getRequestId() { + return requestId; + } + + public RequestParsingInfo setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public RequestParsingInfo setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + return this; + } + + public String getSourceApplicationName() { + return sourceApplicationName; + } + + public RequestParsingInfo setSourceApplicationName(String sourceApplicationName) { + this.sourceApplicationName = sourceApplicationName; + return this; + } + + public boolean isForceAuthentication() { + return forceAuthentication; + } + + public RequestParsingInfo setForceAuthentication(boolean forceAuthentication) { + this.forceAuthentication = forceAuthentication; + return this; + } + + public String getAuthLevelComparison() { + return authLevelComparison; + } + + public RequestParsingInfo setAuthLevelComparison(String authLevelComparison) { + this.authLevelComparison = authLevelComparison; + return this; + } + + public List getRequestedAuthLevels() { + return requestedAuthLevels; + } + + public RequestParsingInfo setRequestedAuthLevels(List requestedAuthLevels) { + this.requestedAuthLevels = requestedAuthLevels; + return this; + } + + public String getRelayState() { + return relayState; + } + + public RequestParsingInfo setRelayState(String relayState) { + this.relayState = relayState; + return this; + } + + public String getResponseUrl() { + return responseUrl; + } + + public RequestParsingInfo setResponseUrl(String responseUrl) { + this.responseUrl = responseUrl; + return this; + } + + public List getRequestedScopes() { + return requestedScopes; + } + + public RequestParsingInfo setRequestedScopes(List requestedScopes) { + this.requestedScopes = requestedScopes; + return this; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingStatus.java b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingStatus.java new file mode 100644 index 0000000..cdb00b2 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingStatus.java @@ -0,0 +1,26 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration.model; + +public enum RequestParsingStatus { + OK, RESPONSE_ERROR, FATAL_ERROR +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/RequestValidationResult.java b/src/main/java/net/identio/server/service/orchestration/model/RequestValidationResult.java new file mode 100644 index 0000000..e29dbc3 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/RequestValidationResult.java @@ -0,0 +1,75 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.orchestration.model; + +public class RequestValidationResult { + + private ValidationStatus validationStatus; + private String errorStatus; + private ResponseData responseData; + private String transactionId; + private String sessionId; + + public ValidationStatus getValidationStatus() { + return validationStatus; + } + + public RequestValidationResult setValidationStatus(ValidationStatus state) { + this.validationStatus = state; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public RequestValidationResult setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public ResponseData getResponseData() { + return responseData; + } + + public RequestValidationResult setResponseData(ResponseData responseData) { + this.responseData = responseData; + return this; + } + + public String getTransactionId() { + return transactionId; + } + + public RequestValidationResult setTransactionId(String transactionId) { + this.transactionId = transactionId; + return this; + } + + public String getSessionId() { + return sessionId; + } + + public RequestValidationResult setSessionId(String sessionId) { + this.sessionId = sessionId; + return this; + } +} diff --git a/src/main/java/net/identio/server/service/orchestration/model/ResponseData.java b/src/main/java/net/identio/server/service/orchestration/model/ResponseData.java new file mode 100644 index 0000000..912312f --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/ResponseData.java @@ -0,0 +1,56 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration.model; + +public class ResponseData { + + private String url; + private String data; + private String relayState; + + public String getUrl() { + return url; + } + + public ResponseData setUrl(String url) { + this.url = url; + return this; + } + + public String getData() { + return data; + } + + public ResponseData setData(String data) { + this.data = data; + return this; + } + + public String getRelayState() { + return relayState; + } + + public ResponseData setRelayState(String relayState) { + this.relayState = relayState; + return this; + } +} diff --git a/src/main/java/net/identio/server/model/SamlAuthRequestGenerationResult.java b/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java similarity index 64% rename from src/main/java/net/identio/server/model/SamlAuthRequestGenerationResult.java rename to src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java index ee60a34..58d36ef 100644 --- a/src/main/java/net/identio/server/model/SamlAuthRequestGenerationResult.java +++ b/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java @@ -1,30 +1,31 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ -package net.identio.server.model; +package net.identio.server.service.orchestration.model; import net.identio.saml.Endpoint; public class SamlAuthRequestGenerationResult { private boolean success; - private ErrorStatus errorStatus; + private String errorStatus; private Endpoint targetEndpoint; private String serializedRequest; private String relayState; @@ -41,11 +42,11 @@ public SamlAuthRequestGenerationResult setSuccess(boolean success) { return this; } - public ErrorStatus getErrorStatus() { + public String getErrorStatus() { return errorStatus; } - public SamlAuthRequestGenerationResult setErrorStatus(ErrorStatus errorStatus) { + public SamlAuthRequestGenerationResult setErrorStatus(String errorStatus) { this.errorStatus = errorStatus; return this; } diff --git a/src/main/java/net/identio/server/service/orchestration/model/ValidationStatus.java b/src/main/java/net/identio/server/service/orchestration/model/ValidationStatus.java new file mode 100644 index 0000000..1f3f6a4 --- /dev/null +++ b/src/main/java/net/identio/server/service/orchestration/model/ValidationStatus.java @@ -0,0 +1,26 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.orchestration.model; + +public enum ValidationStatus { + RESPONSE, CONSENT, ERROR, CHALLENGE, AUTH +} diff --git a/src/main/java/net/identio/server/service/saml/MetadataService.java b/src/main/java/net/identio/server/service/saml/MetadataService.java index c8d3184..f91b2e9 100644 --- a/src/main/java/net/identio/server/service/saml/MetadataService.java +++ b/src/main/java/net/identio/server/service/saml/MetadataService.java @@ -19,6 +19,22 @@ License, or (at your option) any later version. */ package net.identio.server.service.saml; +import net.identio.saml.*; +import net.identio.saml.exceptions.InvalidSignatureException; +import net.identio.saml.exceptions.TechnicalException; +import net.identio.saml.exceptions.UnsignedSAMLObjectException; +import net.identio.saml.exceptions.UntrustedSignerException; +import net.identio.server.exceptions.InitializationException; +import net.identio.server.model.IdentioConfiguration; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.utils.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Scope; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -27,37 +43,10 @@ License, or (at your option) any later version. import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; - -import net.identio.saml.Endpoint; -import net.identio.saml.IdpSsoDescriptor; -import net.identio.saml.Metadata; -import net.identio.saml.MetadataBuilder; -import net.identio.saml.SamlConstants; -import net.identio.saml.SpSsoDescriptor; -import net.identio.saml.Validator; -import net.identio.saml.exceptions.InvalidSignatureException; -import net.identio.saml.exceptions.TechnicalException; -import net.identio.saml.exceptions.UnsignedSAMLObjectException; -import net.identio.saml.exceptions.UntrustedSignerException; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.model.IdentioConfiguration; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.FileUtils; - @Service @Scope("singleton") public class MetadataService { @@ -156,8 +145,8 @@ private void initIdpMetadata() throws TechnicalException, InitializationExceptio LOG.info("* {}", idpMetadata.getEntityID()); } - private void loadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, - UntrustedSignerException, InvalidSignatureException, NoSuchAlgorithmException, IOException { + private void loadMetadata(String filename) throws TechnicalException, + NoSuchAlgorithmException, IOException { File file = new File(filename); @@ -191,8 +180,7 @@ private void loadMetadata(String filename) throws TechnicalException, UnsignedSA loadedSpFiles.put(filename, fileProperties); } - private void unloadMetadata(String filename) throws TechnicalException, UnsignedSAMLObjectException, - UntrustedSignerException, InvalidSignatureException { + private void unloadMetadata(String filename) { LOG.info("Unloading SAML SP metadata: {}", filename); diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index 5609af2..f9b809e 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -19,11 +19,20 @@ License, or (at your option) any later version. */ package net.identio.server.service.saml; -import java.io.IOException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.zip.DataFormatException; - +import net.identio.saml.*; +import net.identio.saml.exceptions.*; +import net.identio.server.exceptions.InitializationException; +import net.identio.server.exceptions.SamlException; +import net.identio.server.exceptions.UnknownAuthLevelException; +import net.identio.server.model.*; +import net.identio.server.service.authpolicy.AuthPolicyService; +import net.identio.server.service.authpolicy.model.AuthPolicyDecision; +import net.identio.server.service.configuration.ConfigurationService; +import net.identio.server.service.orchestration.model.RequestParsingInfo; +import net.identio.server.service.orchestration.model.RequestParsingStatus; +import net.identio.server.service.orchestration.model.ResponseData; +import net.identio.server.service.orchestration.model.SamlAuthRequestGenerationResult; +import net.identio.server.utils.DecodeUtils; import org.apache.xml.security.exceptions.Base64DecodingException; import org.joda.time.DateTime; import org.slf4j.Logger; @@ -33,39 +42,10 @@ License, or (at your option) any later version. import org.springframework.stereotype.Service; import org.springframework.web.util.UriUtils; -import net.identio.saml.Assertion; -import net.identio.saml.AssertionBuilder; -import net.identio.saml.AuthentRequest; -import net.identio.saml.AuthentRequestBuilder; -import net.identio.saml.AuthentResponse; -import net.identio.saml.AuthentResponseBuilder; -import net.identio.saml.Endpoint; -import net.identio.saml.IdpSsoDescriptor; -import net.identio.saml.Metadata; -import net.identio.saml.SamlConstants; -import net.identio.saml.Signer; -import net.identio.saml.SpSsoDescriptor; -import net.identio.saml.Validator; -import net.identio.saml.exceptions.InvalidRequestException; -import net.identio.saml.exceptions.InvalidSignatureException; -import net.identio.saml.exceptions.TechnicalException; -import net.identio.saml.exceptions.UnsignedSAMLObjectException; -import net.identio.saml.exceptions.UntrustedSignerException; -import net.identio.server.exceptions.InitializationException; -import net.identio.server.exceptions.SamlException; -import net.identio.server.exceptions.UnknownAuthLevelException; -import net.identio.server.model.AuthLevel; -import net.identio.server.model.AuthPolicyDecision; -import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.AuthSession; -import net.identio.server.model.IdentioConfiguration; -import net.identio.server.model.ProtocolType; -import net.identio.server.model.SamlAuthRequestGenerationResult; -import net.identio.server.model.SamlInboundRequest; -import net.identio.server.model.UserSession; -import net.identio.server.service.authpolicy.AuthPolicyService; -import net.identio.server.service.configuration.ConfigurationService; -import net.identio.server.utils.DecodeUtils; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.zip.DataFormatException; @Service @Scope("singleton") @@ -111,11 +91,11 @@ private void initSigner(IdentioConfiguration config) throws TechnicalException { SamlConstants.SIGNATURE_ALG_RSA_SHA256); } - public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest request) { + public RequestParsingInfo validateAuthentRequest(SamlInboundRequest request) { - LOG.debug("Starting SAML Authentication Request validation..."); + LOG.debug("Starting SAML Authentication Request orchestration..."); - AuthRequestValidationResult result = new AuthRequestValidationResult(); + RequestParsingInfo result = new RequestParsingInfo(); result.setProtocolType(ProtocolType.SAML); @@ -125,7 +105,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req ar = AuthentRequestBuilder.getInstance().build(request.getSerializedRequest(), false); } catch (TechnicalException | InvalidRequestException e1) { LOG.error("Impossible to build AuthentRequest"); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); + return result.setStatus(RequestParsingStatus.FATAL_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); } // Extract interesting values @@ -139,7 +120,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req if (destinationEndpoint == null) { LOG.error("No suitable response endpoint found"); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + return result.setStatus(RequestParsingStatus.FATAL_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) @@ -154,7 +136,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req try { requestedAuthLevels.add(authPolicyService.getAuthLevelByUrn(authLevelString)); } catch (UnknownAuthLevelException e) { - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_NO_AUTHN_CONTEXT); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_NO_AUTHN_CONTEXT); } } @@ -174,14 +157,16 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req // The request issuer field cannot be null if (requestIssuer == null) { LOG.error("Request Issuer is empty"); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); } // Check if the issuer is registered Validator validator = metadataService.getSpValidator(requestIssuer); if (validator == null) { LOG.error("No validator found for issuer {}", requestIssuer); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); } // Check that we are the recipient of the Authentication Request @@ -189,7 +174,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req if (destination == null) { LOG.error("No destination specified in request"); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } else { @@ -205,7 +191,8 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req } if (!endpointFound) { LOG.error("The request destination doesn't match server SAML endpoints"); - return result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); } } @@ -217,14 +204,14 @@ public AuthRequestValidationResult validateAuthentRequest(SamlInboundRequest req } LOG.debug("* Request is valid"); - result.setSuccess(true); + result.setStatus(RequestParsingStatus.OK); return result; } private boolean validateRedirectRequest(Validator validator, SamlInboundRequest request, - AuthRequestValidationResult result) { + RequestParsingInfo result) { LOG.debug("Validate query parameters of HTTP-Redirect Binding"); @@ -232,7 +219,8 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest try { signature = DecodeUtils.decode(request.getSignatureValue(), false); } catch (Base64DecodingException | IOException | DataFormatException e) { - result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); return false; } String signedInfo = request.getSignedInfo(); @@ -246,7 +234,8 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest validator.validate(signedInfo, signature, sigAlg); } catch (NoSuchAlgorithmException | TechnicalException | InvalidSignatureException e) { LOG.error("Request signature is invalid"); - result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -258,7 +247,8 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { LOG.error("Unsigned requests are not supported."); - result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } } @@ -266,7 +256,7 @@ private boolean validateRedirectRequest(Validator validator, SamlInboundRequest return true; } - private boolean validatePostRequest(Validator validator, AuthentRequest ar, AuthRequestValidationResult result) { + private boolean validatePostRequest(Validator validator, AuthentRequest ar, RequestParsingInfo result) { LOG.debug("Validate query parameters of HTTP-POST Binding"); @@ -279,7 +269,7 @@ private boolean validatePostRequest(Validator validator, AuthentRequest ar, Auth } catch (NoSuchAlgorithmException | UnsignedSAMLObjectException | TechnicalException | UntrustedSignerException | InvalidSignatureException e) { LOG.error("Request signature is invalid"); - result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -290,7 +280,7 @@ private boolean validatePostRequest(Validator validator, AuthentRequest ar, Auth if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { LOG.error("Unsigned requests are not supported."); - result.setSuccess(false).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); return false; } @@ -299,19 +289,19 @@ private boolean validatePostRequest(Validator validator, AuthentRequest ar, Auth return true; } - public String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestValidationResult result, + public ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo requestParsingInfo, UserSession userSession) throws SamlException { LOG.debug("Generating a new SAML Response"); - String spEntityID = result.getSourceApplicationName(); - String requestID = result.getRequestId(); + String spEntityID = requestParsingInfo.getSourceApplicationName(); + String requestID = requestParsingInfo.getRequestId(); String userId = userSession.getUserId(); AuthSession authSession = decision.getValidatedAuthSession(); String authnLevel = authSession.getAuthLevel().getUrn(); DateTime authnInstant = authSession.getAuthInstant(); String sessionId = userSession.getId(); - String destinationUrl = result.getResponseUrl(); + String destinationUrl = requestParsingInfo.getResponseUrl(); // Determine the assertion consumer endpoint @@ -346,7 +336,11 @@ public String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestVa LOG.debug("* SAML response signed"); - return DecodeUtils.encode(response.toString().getBytes(), false); + String data = DecodeUtils.encode(response.toString().getBytes(), false); + + return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) + .setData(data) + .setRelayState(requestParsingInfo.getRelayState()); } catch (TechnicalException | IOException ex) { String message = "Technical error when building SAML response"; @@ -355,11 +349,11 @@ public String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestVa } } - public String generateErrorResponse(AuthRequestValidationResult result) throws SamlException { + public ResponseData generateErrorResponse(RequestParsingInfo requestParsingInfo) throws SamlException { LOG.debug("Generating a new SAML Error Response"); - String destinationUrl = result.getResponseUrl(); + String destinationUrl = requestParsingInfo.getResponseUrl(); if (destinationUrl == null) { String message = "* Destination URL cannot be null"; @@ -373,11 +367,15 @@ public String generateErrorResponse(AuthRequestValidationResult result) throws S // Build the response AuthentResponse response = AuthentResponseBuilder.getInstance() .setIssuer(metadataService.getIdpMetadata().getEntityID()) - .setStatus(false, result.getErrorStatus()).setDestination(destinationUrl).build(); + .setStatus(false, requestParsingInfo.getErrorStatus()).setDestination(destinationUrl).build(); LOG.debug("* SAML response built"); - return DecodeUtils.encode(response.toString().getBytes(), false); + String data = DecodeUtils.encode(response.toString().getBytes(), false); + + return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) + .setData(data) + .setRelayState(requestParsingInfo.getRelayState()); } catch (TechnicalException | IOException ex) { String message = "Technical error when building SAML response"; @@ -435,7 +433,7 @@ private Endpoint findRequestEndpoint(Metadata remoteIdpMetadata) { } public SamlAuthRequestGenerationResult generateAuthentRequest(Metadata remoteIdpMetadata, - ArrayList requestedAuthnContext, String comparison, String transactionId) throws SamlException { + ArrayList requestedAuthnContext, String comparison, String transactionId) throws SamlException { LOG.debug("Generating a new SAML Request"); diff --git a/src/main/java/net/identio/server/service/transaction/TransactionService.java b/src/main/java/net/identio/server/service/transaction/TransactionService.java index a5acb07..8e6a90d 100644 --- a/src/main/java/net/identio/server/service/transaction/TransactionService.java +++ b/src/main/java/net/identio/server/service/transaction/TransactionService.java @@ -19,20 +19,19 @@ License, or (at your option) any later version. */ package net.identio.server.service.transaction; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import net.identio.server.service.orchestration.exceptions.WebSecurityException; +import net.identio.server.service.transaction.model.TransactionData; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - -import net.identio.server.model.TransactionData; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; @Service @Scope("singleton") @@ -73,7 +72,7 @@ public void removeTransactionData(TransactionData transactionData) { transactionCache.invalidate(transactionData.getTransactionId()); } - public TransactionData getTransaction(String transactionId) { + public TransactionData fetchTransaction(String transactionId) { if (transactionId == null) { return new TransactionData(); @@ -88,4 +87,29 @@ public TransactionData getTransaction(String transactionId) { } } + public TransactionData getTransaction(String sessionId, String transactionId) throws WebSecurityException { + + LOG.debug("Security verification of coherence between transaction ID and session ID"); + + TransactionData transactionData = fetchTransaction(transactionId); + + if (transactionData.getTransactionId() == null) { + String message = "Could not find a valid transaction"; + LOG.error(message); + throw new WebSecurityException(message); + } + + if (!sessionId.equals(transactionData.getUserSession().getId())) { + removeTransactionData(transactionData); + + String message = "Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"; + LOG.error(message); + throw new WebSecurityException(message); + } + + LOG.debug("Security verification OK"); + + return transactionData; + } + } diff --git a/src/main/java/net/identio/server/service/transaction/model/TransactionData.java b/src/main/java/net/identio/server/service/transaction/model/TransactionData.java new file mode 100644 index 0000000..72de9a0 --- /dev/null +++ b/src/main/java/net/identio/server/service/transaction/model/TransactionData.java @@ -0,0 +1,112 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.service.transaction.model; + +import net.identio.server.model.*; +import net.identio.server.service.orchestration.model.RequestParsingInfo; + +import java.util.ArrayList; +import java.util.HashSet; + +public class TransactionData { + + private String transactionId; + private UserSession userSession; + private RequestParsingInfo requestParsingInfo; + private ArrayList targetAuthLevels; + private HashSet targetAuthMethods = new HashSet<>(); + private AuthMethod selectedAuthMethod; + private TransactionState transactionState; + private String samlProxyRequestId; + private ProtocolType protocolType; + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public UserSession getUserSession() { + return userSession; + } + + public void setUserSession(UserSession userSession) { + this.userSession = userSession; + } + + public RequestParsingInfo getRequestParsingInfo() { + return requestParsingInfo; + } + + public void setRequestParsingInfo(RequestParsingInfo requestParsingInfo) { + this.requestParsingInfo = requestParsingInfo; + } + + public ArrayList getTargetAuthLevels() { + return targetAuthLevels; + } + + public void setTargetAuthLevels(ArrayList targetAuthLevels) { + this.targetAuthLevels = targetAuthLevels; + } + + public HashSet getTargetAuthMethods() { + return targetAuthMethods; + } + + public void setTargetAuthMethods(HashSet targetAuthMethods) { + this.targetAuthMethods = targetAuthMethods; + } + + public AuthMethod getSelectedAuthMethod() { + return selectedAuthMethod; + } + + public void setSelectedAuthMethod(AuthMethod selectedAuthMethod) { + this.selectedAuthMethod = selectedAuthMethod; + } + + public TransactionState getState() { + return transactionState; + } + + public void setState(TransactionState transactionState) { + this.transactionState = transactionState; + } + + public String getSamlProxyRequestId() { + return samlProxyRequestId; + } + + public void setSamlProxyRequestId(String samlProxyRequestId) { + this.samlProxyRequestId = samlProxyRequestId; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public void setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + } +} diff --git a/src/main/java/net/identio/server/service/transaction/model/TransactionState.java b/src/main/java/net/identio/server/service/transaction/model/TransactionState.java new file mode 100644 index 0000000..2625c4c --- /dev/null +++ b/src/main/java/net/identio/server/service/transaction/model/TransactionState.java @@ -0,0 +1,26 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +package net.identio.server.service.transaction.model; + +public enum TransactionState { + AUTH, CONSENT +} diff --git a/src/main/java/net/identio/server/service/usersession/UserSessionService.java b/src/main/java/net/identio/server/service/usersession/UserSessionService.java index 79dd68d..71aa4a3 100644 --- a/src/main/java/net/identio/server/service/usersession/UserSessionService.java +++ b/src/main/java/net/identio/server/service/usersession/UserSessionService.java @@ -19,22 +19,20 @@ License, or (at your option) any later version. */ package net.identio.server.service.usersession; -import java.util.UUID; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import net.identio.server.model.UserSession; +import net.identio.server.service.configuration.ConfigurationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; - -import net.identio.server.model.UserSession; -import net.identio.server.service.configuration.ConfigurationService; +import java.util.UUID; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; @Service @Scope("singleton") diff --git a/src/main/java/net/identio/server/service/validation/ValidationService.java b/src/main/java/net/identio/server/service/validation/ValidationService.java deleted file mode 100644 index cbbd802..0000000 --- a/src/main/java/net/identio/server/service/validation/ValidationService.java +++ /dev/null @@ -1,415 +0,0 @@ -/* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.service.validation; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.stream.Collectors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Service; - -import net.identio.server.exceptions.AuthMethodNotAllowedException; -import net.identio.server.exceptions.SamlException; -import net.identio.server.exceptions.UnknownAuthMethodException; -import net.identio.server.exceptions.ValidationException; -import net.identio.server.model.AuthLevel; -import net.identio.server.model.AuthMethod; -import net.identio.server.model.AuthPolicyDecision; -import net.identio.server.model.AuthRequestValidationResult; -import net.identio.server.model.Authentication; -import net.identio.server.model.AuthenticationResult; -import net.identio.server.model.AuthenticationResultStatus; -import net.identio.server.model.ErrorStatus; -import net.identio.server.model.InboundRequest; -import net.identio.server.model.OAuthInboundRequest; -import net.identio.server.model.ProtocolType; -import net.identio.server.model.SamlAuthMethod; -import net.identio.server.model.SamlAuthRequestGenerationResult; -import net.identio.server.model.SamlInboundRequest; -import net.identio.server.model.State; -import net.identio.server.model.TransactionData; -import net.identio.server.model.UserSession; -import net.identio.server.model.ValidationResult; -import net.identio.server.service.authentication.AuthenticationService; -import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; -import net.identio.server.service.authpolicy.AuthPolicyService; -import net.identio.server.service.oauth.OAuthService; -import net.identio.server.service.saml.SamlService; -import net.identio.server.service.transaction.TransactionService; -import net.identio.server.service.usersession.UserSessionService; - -@Service -@Scope("singleton") -public class ValidationService { - - private static final Logger LOG = LoggerFactory.getLogger(ValidationService.class); - - @Autowired - private SamlService samlService; - - @Autowired - private UserSessionService userSessionService; - - @Autowired - private OAuthService oauthService; - - @Autowired - private AuthPolicyService authPolicyService; - - @Autowired - private TransactionService transactionService; - - @Autowired - private AuthenticationService authenticationService; - - @Autowired - private SamlAuthenticationProvider samlAuthenticationProvider; - - public ValidationResult validateAuthentRequest(InboundRequest request, String sessionId) - throws ValidationException { - - ValidationResult validationResult = new ValidationResult(); - - // Validate the request - AuthRequestValidationResult arValidationResult = null; - - if (request instanceof SamlInboundRequest) { - arValidationResult = samlService.validateAuthentRequest((SamlInboundRequest) request); - } - if (request instanceof OAuthInboundRequest) { - arValidationResult = oauthService.validateAuthentRequest((OAuthInboundRequest) request); - } - - validationResult.setArValidationResult(arValidationResult); - - if (!arValidationResult.isSuccess()) { - - if (arValidationResult.getResponseUrl() != null) { - validationResult.setState(State.RESPONSE); - validationResult.setResponseData(generateFatalErrorResponse(arValidationResult)); - } - else { - validationResult.setState(State.ERROR); - } - - return validationResult; - } - - TransactionData transactionData = transactionService.createTransaction(); - UserSession userSession = userSessionService.getUserSession(sessionId); - transactionData.setUserSession(userSession); - - validationResult.setTransactionId(transactionData.getTransactionId()); - validationResult.setSessionId(userSession.getId()); - - // Determine target auth levels and auth methods - ArrayList targetAuthLevels = authPolicyService.determineTargetAuthLevel(arValidationResult); - HashSet targetAuthMethods = authPolicyService.determineTargetAuthMethods(targetAuthLevels); - - // Check if previous authentications match - AuthPolicyDecision decision = authPolicyService.checkPreviousAuthSessions(userSession, targetAuthLevels); - - validationResult.setState(decision.getNextState()); - - if (decision.getNextState() == State.RESPONSE) { - validationResult.setResponseData(generateSuccessResponse(decision, arValidationResult, transactionData)); - } else { - // Save data that will need later in the transaction - transactionData.setState(decision.getNextState()); - transactionData.setArValidationResult(arValidationResult); - transactionData.setTargetAuthLevels(targetAuthLevels); - transactionData.setTargetAuthMethods(targetAuthMethods); - } - - return validationResult; - } - - public ValidationResult validateTransparentAuthentication(ValidationResult validationResult, - Authentication authentication) throws ValidationException { - - LOG.debug("Check for transparent authentication"); - - // Fetch transaction - // As we just created the transaction, there is no need to check the - // coherence with the session - TransactionData transactionData = transactionService.getTransaction(validationResult.getTransactionId()); - UserSession userSession = transactionData.getUserSession(); - - if (authentication != null) { - - AuthenticationResult result = authenticationService.validateTransparent(authentication, transactionData); - - if (result != null && result.getStatus() == AuthenticationResultStatus.SUCCESS) { - - AuthPolicyDecision decision = authPolicyService.checkAuthPolicyCompliance(userSession, result, - transactionData.getTargetAuthLevels(), transactionData.getSelectedAuthMethod(), - transactionData.getState()); - - validationResult.setState(decision.getNextState()); - - if (decision.getNextState() == State.RESPONSE) { - - validationResult.setResponseData(generateSuccessResponse(decision, - validationResult.getArValidationResult(), transactionData)); - } - - return validationResult; - } - - } - - return validationResult; - } - - public ValidationResult validateExplicitAuthentication(String transactionId, String sessionId, - String authMethodName, Authentication authentication) throws ValidationException { - - LOG.debug("Validating explicit authentication: {}", authMethodName); - - TransactionData transactionData = getTransaction(sessionId, transactionId); - - ValidationResult validationResult = new ValidationResult(); - validationResult.setArValidationResult(transactionData.getArValidationResult()); - validationResult.setSessionId(sessionId); - validationResult.setTransactionId(transactionId); - - // Try to map the authmethodname to a known method - AuthMethod authMethod = null; - - if (authMethodName != null) { - try { - authMethod = authPolicyService.getAuthMethodByName(authMethodName); - } catch (UnknownAuthMethodException e) { - return generateTemporaryErrorResponse(validationResult, transactionData, - ErrorStatus.AUTH_METHOD_UNKNOWN); - } - } else { - // The authentication method name is not provided, we use the method - // stored in the transaction - AuthMethod transactionAuthMethod = transactionData.getSelectedAuthMethod(); - - if (transactionAuthMethod != null) { - authMethod = transactionAuthMethod; - } else { - return generateTemporaryErrorResponse(validationResult, transactionData, - ErrorStatus.AUTH_METHOD_UNKNOWN); - } - } - - if (authentication == null) { - return generateTemporaryErrorResponse(validationResult, transactionData, ErrorStatus.AUTH_NO_CREDENTIALS); - } else { - - if (transactionData.getState() == State.AUTH) { - transactionData.setSelectedAuthMethod(authMethod); - } - - // Check that the authentication method is listed in the allowed - // methods for this transaction - try { - authPolicyService.checkAllowedAuthMethods(transactionData.getState(), - transactionData.getTargetAuthMethods(), transactionData.getSelectedAuthMethod(), authMethod); - } catch (UnknownAuthMethodException e) { - return generateTemporaryErrorResponse(validationResult, transactionData, - ErrorStatus.AUTH_METHOD_UNKNOWN); - } catch (AuthMethodNotAllowedException e) { - return generateTemporaryErrorResponse(validationResult, transactionData, - ErrorStatus.AUTH_METHOD_NOT_ALLOWED); - } - - AuthenticationResult authResult = authenticationService.validateExplicit(authMethod, authentication, - transactionData); - - if (authResult != null) { - - switch (authResult.getStatus()) { - - case SUCCESS: - - AuthPolicyDecision decision = authPolicyService.checkAuthPolicyCompliance( - transactionData.getUserSession(), authResult, transactionData.getTargetAuthLevels(), - transactionData.getSelectedAuthMethod(), transactionData.getState()); - - validationResult.setState(decision.getNextState()); - transactionData.setState(decision.getNextState()); - - if (decision.getNextState() == State.RESPONSE) { - validationResult.setResponseData(generateSuccessResponse(decision, - transactionData.getArValidationResult(), transactionData)); - } - break; - - case FAIL: - validationResult.setState(transactionData.getState()); - validationResult.setErrorStatus(authResult.getErrorStatus()); - break; - - case CHALLENGE: - validationResult.setState(transactionData.getState()); - validationResult.setChallengeType(authResult.getChallengeType()); - validationResult.setChallengeValue(authResult.getChallengeValue()); - break; - - default: - String message = "Unknown transaction state"; - LOG.error(message); - throw new ValidationException(message); - } - } - - return validationResult; - } - - } - - public List getAuthMethods(String transactionId, String sessionId) throws ValidationException { - - TransactionData transactionData = getTransaction(sessionId, transactionId); - - switch (transactionData.getState()) { - case AUTH: - return transactionData.getTargetAuthMethods().stream().filter(x -> x.isExplicit()) - .sorted((x1, x2) -> x1.getName().compareTo(x2.getName())).collect(Collectors.toList()); - - case STEP_UP_AUTHENTICATION: - return Arrays.asList(transactionData.getSelectedAuthMethod().getStepUpAuthentication().getAuthMethod()); - default: - return null; - } - } - - public SamlAuthRequestGenerationResult initSamlRequest(String transactionId, String sessionId, - String authMethodName) throws ValidationException { - - TransactionData transactionData = getTransaction(sessionId, transactionId); - - AuthMethod authMethod = null; - try { - authMethod = authPolicyService.getAuthMethodByName(authMethodName); - } catch (UnknownAuthMethodException e) { - return new SamlAuthRequestGenerationResult().setSuccess(false) - .setErrorStatus(ErrorStatus.AUTH_METHOD_UNKNOWN); - } - - transactionData.setSelectedAuthMethod(authMethod); - - try { - authPolicyService.checkAllowedAuthMethods(transactionData.getState(), - transactionData.getTargetAuthMethods(), transactionData.getSelectedAuthMethod(), authMethod); - } catch (UnknownAuthMethodException e) { - return new SamlAuthRequestGenerationResult().setSuccess(false) - .setErrorStatus(ErrorStatus.AUTH_METHOD_UNKNOWN); - } catch (AuthMethodNotAllowedException e) { - return new SamlAuthRequestGenerationResult().setSuccess(false) - .setErrorStatus(ErrorStatus.AUTH_METHOD_NOT_ALLOWED); - } - - try { - SamlAuthRequestGenerationResult result = samlAuthenticationProvider.initRequest((SamlAuthMethod) authMethod, - transactionData.getTargetAuthLevels(), transactionId); - - transactionData.setSamlProxyRequestId(result.getRequestId()); - return result; - - } catch (SamlException e) { - String message = "An error occured when generating authent request"; - LOG.error(message); - throw new ValidationException(message, e); - } - } - - private String generateSuccessResponse(AuthPolicyDecision decision, AuthRequestValidationResult arValidationResult, - TransactionData transactionData) throws ValidationException { - - if (arValidationResult.getProtocolType() == ProtocolType.SAML) { - - try { - return samlService.generateSuccessResponse(decision, arValidationResult, - transactionData.getUserSession()); - } catch (SamlException e) { - String message = "An error occured when generating response"; - LOG.error(message); - throw new ValidationException(message, e); - } finally { - transactionService.removeTransactionData(transactionData); - } - } else { - return oauthService.generateSuccessResponse(arValidationResult, transactionData.getUserSession()); - } - } - - private String generateFatalErrorResponse(AuthRequestValidationResult arValidationResult) - throws ValidationException { - - if (arValidationResult.getProtocolType() == ProtocolType.SAML) { - - try { - return samlService.generateErrorResponse(arValidationResult); - } catch (SamlException e) { - String message = "An error occured when generating response"; - LOG.error(message); - throw new ValidationException(message, e); - } - } else { - return oauthService.generateErrorResponse(arValidationResult); - } - } - - private ValidationResult generateTemporaryErrorResponse(ValidationResult validationResult, - TransactionData transactionData, ErrorStatus status) { - - // The state remains untouched - validationResult.setState(transactionData.getState()); - validationResult.setErrorStatus(status); - return validationResult; - } - - private TransactionData getTransaction(String sessionId, String transactionId) throws ValidationException { - - LOG.debug("Security verification of coherence between transaction ID and session ID"); - - TransactionData transactionData = transactionService.getTransaction(transactionId); - - if (transactionData.getTransactionId() == null) { - String message = "Could not find a valid transaction"; - LOG.error(message); - throw new ValidationException(message); - } - - if (!sessionId.equals(transactionData.getUserSession().getId())) { - transactionService.removeTransactionData(transactionData); - - String message = "Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"; - LOG.error(message); - throw new ValidationException(message); - } - - LOG.debug("Security verification OK"); - - return transactionData; - } - -} diff --git a/src/main/java/net/identio/server/utils/DecodeUtils.java b/src/main/java/net/identio/server/utils/DecodeUtils.java index 83f4ac8..1b16f52 100644 --- a/src/main/java/net/identio/server/utils/DecodeUtils.java +++ b/src/main/java/net/identio/server/utils/DecodeUtils.java @@ -19,17 +19,17 @@ License, or (at your option) any later version. */ package net.identio.server.utils; +import org.apache.xml.security.exceptions.Base64DecodingException; +import org.apache.xml.security.utils.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; -import org.apache.xml.security.exceptions.Base64DecodingException; -import org.apache.xml.security.utils.Base64; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - public class DecodeUtils { private static final Logger LOG = LoggerFactory.getLogger(DecodeUtils.class); @@ -86,7 +86,7 @@ public static String encode(byte[] data, boolean deflate) throws IOException { String encodedString = null; - byte[] deflatedData = deflate ? deflate(data,true) : data; + byte[] deflatedData = deflate ? deflate(data, true) : data; // First, we decode the B64 string encodedString = Base64.encode(deflatedData).replaceAll("\r", "").replaceAll("\n", ""); @@ -153,7 +153,7 @@ private static byte[] deflate(byte[] data, boolean nowrap) throws IOException { deflater.setInput(data); deflater.finish(); - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);) { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) { byte[] buffer = new byte[1024]; diff --git a/src/main/java/net/identio/server/utils/FileUtils.java b/src/main/java/net/identio/server/utils/FileUtils.java index 30839cc..e20194d 100644 --- a/src/main/java/net/identio/server/utils/FileUtils.java +++ b/src/main/java/net/identio/server/utils/FileUtils.java @@ -19,13 +19,13 @@ License, or (at your option) any later version. */ package net.identio.server.utils; +import org.springframework.security.crypto.codec.Hex; + import java.io.FileInputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import org.springframework.security.crypto.codec.Hex; - public class FileUtils { public static String getFileHash(String filename) throws NoSuchAlgorithmException, IOException { diff --git a/src/main/java/net/identio/server/utils/PasswordUtils.java b/src/main/java/net/identio/server/utils/PasswordUtils.java index 6b07630..6b19cb5 100644 --- a/src/main/java/net/identio/server/utils/PasswordUtils.java +++ b/src/main/java/net/identio/server/utils/PasswordUtils.java @@ -19,10 +19,10 @@ License, or (at your option) any later version. */ package net.identio.server.utils; -import java.io.Console; - import org.springframework.security.crypto.bcrypt.BCrypt; +import java.io.Console; + public class PasswordUtils { public static void main(String[] args) { diff --git a/src/main/java/net/identio/server/utils/SecurityUtils.java b/src/main/java/net/identio/server/utils/SecurityUtils.java index 0b334b1..8957ce5 100644 --- a/src/main/java/net/identio/server/utils/SecurityUtils.java +++ b/src/main/java/net/identio/server/utils/SecurityUtils.java @@ -107,13 +107,13 @@ public static final String escapeLDAPSearchFilter(String filter) { public static final void addCertificateToKeyStore(KeyStore ks, X509Certificate cert, String alias) - throws FileNotFoundException, IOException, CertificateException, KeyStoreException { + throws KeyStoreException { ks.setCertificateEntry(alias, cert); } public static final X509Certificate parseCertificate(String path) - throws FileNotFoundException, IOException, CertificateException { + throws IOException, CertificateException { try (FileInputStream fis = new FileInputStream(path); BufferedInputStream bis = new BufferedInputStream(fis)) { diff --git a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java index dd2ac8f..f40b859 100644 --- a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java @@ -4,11 +4,13 @@ import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import net.identio.server.boot.IdentioServerApplication; -import net.identio.server.model.ProtocolType; -import net.identio.server.model.State; -import net.identio.server.model.api.AuthMethodResponse; -import net.identio.server.model.api.AuthSubmitRequest; -import net.identio.server.model.api.AuthSubmitResponse; +import net.identio.server.mvc.common.model.ApiResponseStatus; +import net.identio.server.mvc.common.model.AuthMethodResponse; +import net.identio.server.mvc.common.model.AuthSubmitRequest; +import net.identio.server.mvc.common.model.AuthSubmitResponse; +import net.identio.server.mvc.oauth.model.ConsentContext; +import net.identio.server.mvc.oauth.model.ConsentRequest; +import net.identio.server.mvc.oauth.model.ConsentResponse; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -22,6 +24,7 @@ import java.io.FileInputStream; import java.security.*; import java.security.interfaces.RSAKey; +import java.util.Arrays; import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -78,9 +81,9 @@ public void oAuthAuthorizeValidRequest() { AuthMethodResponse[].class); assertEquals(HttpStatus.OK, authMethodResponse.getStatusCode()); - assertEquals(authMethodResponse.getBody().length, 1); - assertEquals(authMethodResponse.getBody()[0].getName(), "Local"); - assertEquals(authMethodResponse.getBody()[0].getType(), "local"); + assertEquals(1, authMethodResponse.getBody().length); + assertEquals("Local", authMethodResponse.getBody()[0].getName()); + assertEquals("local", authMethodResponse.getBody()[0].getType()); // Authenticate with local method AuthSubmitRequest authenticationSubmit = new AuthSubmitRequest().setLogin("johndoe").setPassword("password") @@ -92,20 +95,42 @@ public void oAuthAuthorizeValidRequest() { new HttpEntity<>(authenticationSubmit, headers), AuthSubmitResponse.class); - // Check that the authentication is successful and that we get a response + // Check that the authentication is successful and that we're asked for consent AuthSubmitResponse authSubmitResponse = authSubmitResponseEntity.getBody(); assertEquals(HttpStatus.OK, authSubmitResponseEntity.getStatusCode()); - assertNotNull(authSubmitResponse); + assertEquals(ApiResponseStatus.CONSENT, authSubmitResponse.getStatus()); - assertEquals(authSubmitResponse.getState(), State.RESPONSE); - assertEquals(authSubmitResponse.getProtocolType(), ProtocolType.OAUTH); - assertEquals(authSubmitResponse.getRelayState(), "1234"); - assertTrue(authSubmitResponse.getResponse().matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); + // Get information for consent screen + ResponseEntity consentContextEntity = restTemplate.exchange( + getUrlWithPort("/api/authz/consent"), + HttpMethod.GET, + new HttpEntity<>(null, headers), + ConsentContext.class); + + ConsentContext consentContext = consentContextEntity.getBody(); + + assertEquals("Test Client", consentContext.getAudience()); + assertEquals(Arrays.asList("scope.test.1", "scope.test.2"), consentContext.getRequestedScopes()); + assertEquals("/logo/app/test", consentContext.getAudienceLogo()); + + // Send the consent + ConsentRequest consentRequest = new ConsentRequest().setApprovedScopes(Arrays.asList("scope.test.1", "scope.test.2")); + + ResponseEntity consentResponseEntity = restTemplate.exchange( + getUrlWithPort("/api/authz/consent"), + HttpMethod.POST, + new HttpEntity<>(consentRequest, headers), + ConsentResponse.class); + + ConsentResponse consentResponse = consentResponseEntity.getBody(); + + assertEquals(true, consentResponse.isSuccess()); + assertTrue(consentResponse.getResponse().matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); // Parse and validate JWT Pattern pattern = Pattern.compile("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=(.*)&state=1234"); - Matcher matcher = pattern.matcher(authSubmitResponse.getResponse()); + Matcher matcher = pattern.matcher(authSubmitResponse.getDestinationUrl()); Algorithm algorithm = null; try { @@ -123,8 +148,7 @@ public void oAuthAuthorizeValidRequest() { if (matcher.find()) { verifier.verify(matcher.group(1)); - } - else { + } else { fail(); } diff --git a/src/test/resources/oauth-server-config/oauth-clients.yml b/src/test/resources/oauth-server-config/oauth-clients.yml index f75c474..c08c949 100644 --- a/src/test/resources/oauth-server-config/oauth-clients.yml +++ b/src/test/resources/oauth-server-config/oauth-clients.yml @@ -9,3 +9,4 @@ oAuthClients: - http://example.com/cb allowedGrants: - implicit + needConsent: true diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index b3ad153..6469511 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -5,7 +5,7 @@ * @ngdoc overview * @name identioUiApp * @description # identioUiApp - * + * * Main module of the application. */ angular.module( @@ -13,7 +13,7 @@ [ 'ngAnimate', 'ngCookies', 'ngResource', 'ui.router', 'ngSanitize', 'ngTouch', 'pascalprecht.translate' ]).config( function($stateProvider, $urlRouterProvider, $translateProvider) { - + // ** Routing configuration // For any unmatched url, redirect to /state1 $urlRouterProvider.otherwise('/error/'); @@ -37,9 +37,12 @@ url : '/logout', templateUrl : 'views/logout.html', }); - + // ** I18N $translateProvider.translations('en', { + + // UI + IDENTIO_SIGN_IN: 'Sign in to Ident.io', AUTHENTICATION_METHOD: 'Authentication method', USERNAME: 'Username or email address', @@ -50,17 +53,25 @@ SUBMIT: 'Submit', SUBMIT_IN_PROGRESS: 'Submit in progress...', SAML_SECTION_HEADER: 'Alternatively you can login with:', - AUTH_INVALID_CREDENTIALS: 'Invalid username or password', - AUTH_TECHNICAL_ERROR: 'An error occured when validating authentication.' + + ERROR: "An error occured", + + // Errors + 'invalid.credentials': 'Invalid username or password', + 'technical.error': 'An error occured when validating authentication.' + 'Please wait a few seconds and try again', - AUTH_USER_ID_MISMATCH: 'The username doesn’t match the one in session', - AUTH_USER_NOT_UNIQUE: 'The username is not unique in the authentication source', - AUTH_METHOD_UNKNOWN: 'The authentication method is unknown', - AUTH_NO_CREDENTIALS: 'No credentials provided', - AUTH_METHOD_NOT_ALLOWED: 'The authentication method is not allowed' - }) + 'unknown.client': 'The client application is unknown', + 'server.error': 'A server-side error occured', + 'auth.method.unknown': 'The authentication method is unknown', + 'auth.method.not.allowed': 'The authentication method is not allowed', + 'invalid.transaction': 'The transaction identifier is invalid or expired', + 'invalid.request': 'The received request is invalid' + }) .translations('fr', { + + // UI IDENTIO_SIGN_IN: 'Identifiez-vous sur Ident.io', + 'unknown.client': 'L’application client est inconnue', + AUTHENTICATION_METHOD: 'Moyen d’authentification', USERNAME: 'Identifiant', PASSWORD: 'Mot de passe', @@ -70,16 +81,18 @@ SUBMIT: 'Connexion', SUBMIT_IN_PROGRESS: 'Connexion en cours...', SAML_SECTION_HEADER: 'Alternativement, vous pouvez vous identifier sur:', - AUTH_INVALID_CREDENTIALS: 'Identifiant ou mot de passe invalide', - AUTH_TECHNICAL_ERROR: 'Une erreur s’est produite pendant l’authentification. ' + - 'Patientez quelques secondes et réessayez', - AUTH_USER_ID_MISMATCH: 'L’identifiant ne correspond pas à celui en session', - AUTH_USER_NOT_UNIQUE: 'L’identifiant n’est pas unique dans la source ' + - 'd’authentification', - AUTH_METHOD_UNKNOWN: 'La méthode d’authentification est inconnue', - AUTH_NO_CREDENTIALS: 'Aucun identifiant fourni', - AUTH_METHOD_NOT_ALLOWED: 'La méthode d’authentification n’est pas ' + - 'autorisée' + ERROR: "Une erreur s’est produite", + + // Errors + 'invalid.credentials': 'Identifiant ou mot de passe invalide', + 'technical.error': 'Une erreur s’est produite pendant l’authentification. ' + + 'Patientez quelques secondes et réessayez', + 'unknown.client': 'L’application cliente est inconnue', + 'server.error': 'Une erreur serveur s’est produite', + 'auth.method.unknown': 'La méthode d’authentification est inconnue', + 'auth.method.not.allowed': 'La méthode d’authentification est invalide', + 'invalid.transaction': 'L’identifiant de transaction est invalide ou expiré', + 'invalid.request': 'La requête reçue est invalide' }) .registerAvailableLanguageKeys(['en', 'fr'], { 'en_US': 'en', @@ -90,4 +103,4 @@ .determinePreferredLanguage(); }); -})(); \ No newline at end of file +})(); diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index 6973808..a7a05f6 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -98,7 +98,7 @@ var data = response.data; - if (data.state === 'RESPONSE') { + if (data.status === 'RESPONSE') { data.destinationUrl = $sce .trustAsResourceUrl(data.destinationUrl); @@ -129,11 +129,6 @@ vm.error = false; $state.go('auth.challenge'); } - - if (data.state === 'STEP_UP_AUTHENTICATION') { - init(); - vm.state = data.state; - } } function errorHandler(response) { diff --git a/ui/app/scripts/controllers/errorController.js b/ui/app/scripts/controllers/errorController.js index 099ab1c..6cc02bc 100644 --- a/ui/app/scripts/controllers/errorController.js +++ b/ui/app/scripts/controllers/errorController.js @@ -9,15 +9,15 @@ */ angular.module('identioUiApp') .controller('ErrorController', ErrorController); - + ErrorController.$inject = ['$scope', '$state', '$stateParams']; - + function ErrorController($scope, $state, $stateParams) { - + /* jshint validthis: true */ var vm = this; - - vm.message = $stateParams.errorCode; - + + vm.errorId = $stateParams.errorId; + } -})(); \ No newline at end of file +})(); diff --git a/ui/app/scripts/directives/oauth-responder.js b/ui/app/scripts/directives/oauth-responder.js index a4dabd3..035975b 100644 --- a/ui/app/scripts/directives/oauth-responder.js +++ b/ui/app/scripts/directives/oauth-responder.js @@ -5,16 +5,16 @@ angular.module('identioUiApp') .directive('oauthResponder', OauthResponder); OauthResponder.$inject = ['$window']; - + function OauthResponder($window) { return { replace: true, scope: {}, link: function($scope, element, $attrs) { $scope.$on($attrs.event, function(event, data) { - $window.location.href = data.response; + $window.location.href = data.destinationUrl; }); } }; } -})(); \ No newline at end of file +})(); diff --git a/ui/app/scripts/directives/saml-responder.js b/ui/app/scripts/directives/saml-responder.js index 07e8094..95d8537 100644 --- a/ui/app/scripts/directives/saml-responder.js +++ b/ui/app/scripts/directives/saml-responder.js @@ -5,13 +5,13 @@ angular.module('identioUiApp') .directive('samlResponder', SamlResponder); SamlResponder.$inject = ['$timeout']; - + function SamlResponder($timeout) { return { replace: true, scope: {}, template: '
'+ - ''+ + ''+ ''+ '
', link: function($scope, element, $attrs) { @@ -24,4 +24,4 @@ angular.module('identioUiApp') } }; } -})(); \ No newline at end of file +})(); diff --git a/ui/app/views/error.html b/ui/app/views/error.html index e81bd9a..88a2603 100644 --- a/ui/app/views/error.html +++ b/ui/app/views/error.html @@ -1,10 +1,14 @@ + +
+ +
-
-
-

Oops. An error occured

+

+
-

{{error.message}}

+
+ + + -
-
-
\ No newline at end of file + diff --git a/ui/app/views/local.html b/ui/app/views/local.html new file mode 100644 index 0000000..466e09c --- /dev/null +++ b/ui/app/views/local.html @@ -0,0 +1,7 @@ +

+ + +

+ From 3b3d8cd012321722fa6029fc3403a4c259ce916b Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Thu, 17 Aug 2017 17:21:20 +0200 Subject: [PATCH 029/104] Code format and copyright update --- build.gradle | 102 +-- sample-config/logback.xml | 30 +- .../server/boot/BootCustomizationBean.java | 213 ++--- .../server/boot/IdentioServerApplication.java | 43 +- .../server/boot/ServletInitializer.java | 43 +- .../boot/StaticResourceConfiguration.java | 69 +- .../AuthMethodNotAllowedException.java | 49 +- .../exceptions/AuthenticationException.java | 49 +- .../exceptions/ConfigurationException.java | 49 +- .../exceptions/InitializationException.java | 49 +- .../NoAuthMethodFoundException.java | 49 +- .../server/exceptions/SamlException.java | 49 +- .../exceptions/UnknownAuthLevelException.java | 49 +- .../UnknownAuthMethodException.java | 49 +- .../identio/server/model/AppAuthLevel.java | 77 +- .../net/identio/server/model/AuthLevel.java | 85 +- .../net/identio/server/model/AuthMethod.java | 107 +-- .../server/model/AuthMethodConfiguration.java | 167 ++-- .../server/model/AuthPolicyConfiguration.java | 77 +- .../net/identio/server/model/AuthSession.java | 87 +- .../model/AuthorizationConfiguration.java | 49 +- .../server/model/AuthorizationScope.java | 101 +- .../server/model/GlobalConfiguration.java | 179 ++-- .../server/model/IdentioConfiguration.java | 161 ++-- .../identio/server/model/InboundRequest.java | 21 + .../identio/server/model/LdapAuthMethod.java | 169 ++-- .../identio/server/model/LdapPoolConfig.java | 179 ++-- .../identio/server/model/LocalAuthMethod.java | 55 +- .../server/model/OAuthInboundRequest.java | 131 +-- .../model/OAuthServerConfiguration.java | 51 +- .../identio/server/model/ProtocolType.java | 37 +- .../server/model/RadiusAuthMethod.java | 111 +-- .../net/identio/server/model/SamlAuthMap.java | 63 +- .../identio/server/model/SamlAuthMethod.java | 83 +- .../server/model/SamlAuthentication.java | 55 +- .../server/model/SamlIdpConfiguration.java | 215 ++--- .../server/model/SamlInboundRequest.java | 163 ++-- .../server/model/SessionConfiguration.java | 63 +- .../net/identio/server/model/UserSession.java | 105 +-- .../identio/server/model/X509AuthMethod.java | 223 ++--- .../server/mvc/common/AuthentController.java | 35 +- .../mvc/common/DefaultErrorController.java | 51 +- .../GlobalControllerExceptionHandler.java | 63 +- .../server/mvc/common/LogoController.java | 103 +-- .../server/mvc/common/LogoutController.java | 53 +- .../mvc/common/TransparentAuthController.java | 38 +- .../mvc/common/model/ApiErrorResponse.java | 20 +- .../mvc/common/model/AuthMethodResponse.java | 40 +- .../mvc/common/model/AuthSubmitRequest.java | 64 +- .../mvc/common/model/AuthSubmitResponse.java | 160 ++-- .../LaunchSamlAuthenticationResponse.java | 140 +-- .../server/mvc/oauth/ConsentController.java | 35 +- .../server/mvc/oauth/OAuthController.java | 129 +-- .../mvc/oauth/model/ConsentContext.java | 21 + .../mvc/oauth/model/ConsentRequest.java | 21 + .../mvc/oauth/model/ConsentResponse.java | 21 + .../mvc/saml/AssertionConsumerController.java | 99 +- .../server/mvc/saml/MetadataController.java | 75 +- .../mvc/saml/RequestConsumerController.java | 306 +++---- .../server/mvc/saml/ResponderController.java | 81 +- .../AuthenticationProvider.java | 41 +- .../authentication/AuthenticationService.java | 123 +-- .../ldap/LdapAuthenticationProvider.java | 273 +++--- .../ldap/LdapConnectionFactory.java | 227 ++--- .../ldap/LdapSslSocketFactory.java | 149 +-- .../local/FileUserRepository.java | 49 +- .../local/LocalAuthenticationProvider.java | 183 ++-- .../service/authentication/local/User.java | 63 +- .../model/AuthenticationResult.java | 140 +-- .../model/AuthenticationResultStatus.java | 2 +- .../model/UserPasswordAuthentication.java | 76 +- .../model/X509Authentication.java | 68 +- .../radius/RadiusAuthenticationProvider.java | 319 +++---- .../saml/SamlAuthenticationProvider.java | 413 ++++----- .../x509/X509AuthenticationProvider.java | 331 +++---- .../authorization/AuthorizationService.java | 97 +- .../exceptions/NoScopeProvidedException.java | 35 +- .../exceptions/UnknownScopeException.java | 35 +- .../service/authpolicy/AuthPolicyService.java | 367 ++++---- .../authpolicy/model/AuthPolicyDecision.java | 60 +- .../configuration/ConfigurationService.java | 241 ++--- .../server/service/dao/MongoDbDao.java | 35 +- .../service/oauth/OAuthClientRepository.java | 25 +- .../server/service/oauth/OAuthService.java | 35 +- .../FileOAuthClientRepository.java | 81 +- .../oauth/infrastructure/OAuthClientFile.java | 35 +- .../service/oauth/model/OAuthClient.java | 130 +-- .../service/oauth/model/OAuthErrors.java | 21 + .../service/oauth/model/OAuthGrants.java | 29 +- .../oauth/model/OAuthResponseType.java | 27 +- .../AuthOrchestrationService.java | 3 +- .../RequestOrchestrationService.java | 2 +- .../exceptions/ServerException.java | 14 +- .../exceptions/ValidationException.java | 14 +- .../exceptions/WebSecurityException.java | 14 +- .../model/OrchestrationErrorStatus.java | 2 +- .../model/RequestParsingInfo.java | 238 ++--- .../SamlAuthRequestGenerationResult.java | 160 ++-- .../server/service/saml/MetadataService.java | 35 +- .../server/service/saml/SamlService.java | 864 +++++++++--------- .../transaction/TransactionService.java | 137 +-- .../transaction/model/TransactionData.java | 162 ++-- .../userdetails/UserDetailsService.java | 35 +- .../usersession/UserSessionService.java | 127 +-- .../net/identio/server/utils/DecodeUtils.java | 297 +++--- .../net/identio/server/utils/FileUtils.java | 63 +- .../net/identio/server/utils/HttpUtils.java | 65 +- .../identio/server/utils/PasswordUtils.java | 65 +- .../identio/server/utils/SecurityUtils.java | 221 ++--- src/main/resources/application.properties | 20 + src/main/resources/logback.xml | 67 +- .../integ/oauth/InitialRequestTests.java | 21 + .../oauth/OAuthImplicitFullCinematicTest.java | 21 + .../resources/oauth-server-config/logback.xml | 51 +- ui/app/index.html | 97 +- ui/app/views/auth.html | 82 +- ui/app/views/challenge.html | 11 +- ui/app/views/error.html | 6 +- ui/app/views/ldap.html | 4 +- ui/app/views/local.html | 25 +- ui/app/views/logout.html | 12 +- ui/app/views/radius.html | 4 +- 122 files changed, 6186 insertions(+), 5724 deletions(-) diff --git a/build.gradle b/build.gradle index 3db15e6..e4ad744 100644 --- a/build.gradle +++ b/build.gradle @@ -42,63 +42,63 @@ configurations { dependencies { compile("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") { - exclude group: 'org.hibernate', module: 'hibernate-validator' + exclude group: 'org.hibernate', module: 'hibernate-validator' } compile("org.springframework.boot:spring-boot-devtools:${springBootVersion}") compile("org.springframework.security:spring-security-web:4.1.2.RELEASE") compile('org.apache.commons:commons-pool2:2.4.2') - compile('com.github.identio:identio-saml:1.0.2') - compile('com.google.guava:guava:22.0') + compile('com.github.identio:identio-saml:1.0.2') + compile('com.google.guava:guava:22.0') compile('com.github.identio:jradius-client:-SNAPSHOT') compile('com.auth0:java-jwt:3.0.2') - compile('ch.qos.logback:logback-core:1.2.3') - compile('ch.qos.logback:logback-classic:1.2.3') + compile('ch.qos.logback:logback-core:1.2.3') + compile('ch.qos.logback:logback-classic:1.2.3') testCompile("org.springframework.boot:spring-boot-starter-test:${springBootVersion}") testCompile("org.apache.httpcomponents:httpclient:4.5.3") } eclipse { wtp { - facet { + facet { facet name: 'java', version: '1.8' facet name: 'jst.web', version: '3.1' - } + } } project - { - natures "org.springsource.ide.eclipse.gradle.core.nature" - } + { + natures "org.springsource.ide.eclipse.gradle.core.nature" + } } springBoot { - mainClass = "net.identio.server.boot.IdentioServerApplication" + mainClass = "net.identio.server.boot.IdentioServerApplication" } bootRun { - systemProperties = ['logging.config':'file:./config/logback.xml'] + systemProperties = ['logging.config': 'file:./config/logback.xml'] } /// *** UI *** /// node { - // Version of node to use. - version = '5.1.0' + // Version of node to use. + version = '5.1.0' - // Version of npm to use. - npmVersion = '3.9.6' + // Version of npm to use. + npmVersion = '3.9.6' - // Base URL for fetching node distributions (change if you have a mirror). - distBaseUrl = 'https://nodejs.org/dist' + // Base URL for fetching node distributions (change if you have a mirror). + distBaseUrl = 'https://nodejs.org/dist' - // If true, it will download node using above parameters. - // If false, it will try to use globally installed node. - download = true + // If true, it will download node using above parameters. + // If false, it will try to use globally installed node. + download = true - // Set the work directory for unpacking node - workDir = file("${project.buildDir}/ui") + // Set the work directory for unpacking node + workDir = file("${project.buildDir}/ui") - // Set the work directory where node_modules should be located - nodeModulesDir = file("${project.projectDir}/ui") + // Set the work directory where node_modules should be located + nodeModulesDir = file("${project.projectDir}/ui") } grunt { @@ -113,37 +113,37 @@ grunt { } task bowerInstall(type: NodeTask) { - script = file('ui/node_modules/bower/lib/bin/bower.js') - args = ['install', '--allow-root'] - execOverrides { - it.ignoreExitValue = true - it.workingDir = file("${project.projectDir}/ui") - } + script = file('ui/node_modules/bower/lib/bin/bower.js') + args = ['install', '--allow-root'] + execOverrides { + it.ignoreExitValue = true + it.workingDir = file("${project.projectDir}/ui") + } } /// *** Packaging *** /// def distributionsCopySpec = copySpec { into("identio-server") { - - from 'README.md' + + from 'README.md' from 'LICENSE' - + into('bin') { - from 'scripts/password-generator' - from 'scripts/start' - fileMode 0755 + from 'scripts/password-generator' + from 'scripts/start' + fileMode 0755 } into('lib') { - from(jar) - from(project.configurations.runtime) - exclude 'spring-boot-devtools-*' + from(jar) + from(project.configurations.runtime) + exclude 'spring-boot-devtools-*' } into('config') { - from 'sample-config' + from 'sample-config' } into('ui') { - from 'ui/dist' + from 'ui/dist' } } } @@ -154,20 +154,20 @@ npmInstall.mustRunAfter clean jar.mustRunAfter clean task releaseZip(type: Zip, dependsOn: ['clean', 'jar', 'bowerInstall', 'npmInstall', 'grunt_build']) { - description 'Build a release in zip format' - with distributionsCopySpec - archiveName = "identio-server.zip" + description 'Build a release in zip format' + with distributionsCopySpec + archiveName = "identio-server.zip" } -task releaseTarGz(type: Tar, dependsOn: ['clean', 'jar', 'bowerInstall', 'npmInstall', 'grunt_build']) { - description 'Build a release in tar.gz format' - compression = Compression.GZIP - with distributionsCopySpec - archiveName = "identio-server.tar.gz" +task releaseTarGz(type: Tar, dependsOn: ['clean', 'jar', 'bowerInstall', 'npmInstall', 'grunt_build']) { + description 'Build a release in tar.gz format' + compression = Compression.GZIP + with distributionsCopySpec + archiveName = "identio-server.tar.gz" } task release(dependsOn: ['releaseTarGz', 'releaseZip']) { - description 'Build release in zip and tar.gz format' + description 'Build release in zip and tar.gz format' } task wrapper(type: Wrapper) { diff --git a/sample-config/logback.xml b/sample-config/logback.xml index 34091fc..c836e68 100644 --- a/sample-config/logback.xml +++ b/sample-config/logback.xml @@ -2,22 +2,22 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n - - - + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n + + + - - + + - - - - - + + + + + \ No newline at end of file diff --git a/src/main/java/net/identio/server/boot/BootCustomizationBean.java b/src/main/java/net/identio/server/boot/BootCustomizationBean.java index ff913cc..b71e0c3 100644 --- a/src/main/java/net/identio/server/boot/BootCustomizationBean.java +++ b/src/main/java/net/identio/server/boot/BootCustomizationBean.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.boot; @@ -48,94 +49,94 @@ License, or (at your option) any later version. @Configuration public class BootCustomizationBean { - private static final Logger LOG = LoggerFactory.getLogger(BootCustomizationBean.class); - - @Autowired - private ConfigurationService configurationService; - - @Autowired - private X509AuthenticationProvider x509AuthenticationProvider; - - @Bean - public EmbeddedServletContainerFactory servletContainer() { - - TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); - factory.setPort(configurationService.getConfiguration().getGlobalConfiguration().getPort()); - - factory.setSessionTimeout(5, TimeUnit.MINUTES); - - factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { - @Override - public void customize(Connector connector) { - - AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler(); - httpProtocol.setCompression("on"); - httpProtocol.setMaxThreads(150); - - if (configurationService.getConfiguration().getGlobalConfiguration().isSecure()) { - - connector.setSecure(true); - connector.setScheme("https"); - connector.setAttribute("keystoreFile", "file:///" - + configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePath()); - connector.setAttribute("keystorePass", - configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePassword()); - connector.setAttribute("keystoreType", "PKCS12"); - connector.setAttribute("keyAlias", "1"); - connector.setAttribute("sslProtocol", "TLSv1.2"); - connector.setAttribute("sslEnabledProtocols", "+TLSv1.1,+TLSv1.2"); - connector.setAttribute("SSLEnabled", true); - connector.setAttribute("ciphers", - "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"); - connector.setAttribute("server", "Ident.io Server"); - configureTlsClientAuth(connector); - } - } - }); - return factory; - } - - private void configureTlsClientAuth(Connector connector) { - - List x509methods = configurationService.getConfiguration().getAuthMethodConfiguration() - .getX509AuthMethods(); - - if (x509methods != null) { - - try (FileOutputStream fos = new FileOutputStream( - configurationService.getConfiguration().getGlobalConfiguration().getWorkDirectory() - + "/identio-trust.jks")) { - - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(null, null); - - for (X509Certificate cert : x509AuthenticationProvider.getServerTrusts()) { - SecurityUtils.addCertificateToKeyStore(ks, cert, UUID.randomUUID().toString()); - } - - // As the keystore contains only public certs, the password here - // is not relevant - String trustPassword = UUID.randomUUID().toString(); - ks.store(fos, trustPassword.toCharArray()); - - connector.setAttribute("clientAuth", "want"); - connector.setAttribute("truststoreFile", - "file:///" + configurationService.getConfiguration().getGlobalConfiguration().getWorkDirectory() - + "/identio-trust.jks"); - connector.setAttribute("truststorePass", trustPassword); - connector.setAttribute("truststoreType", "JKS"); - - } catch (KeyStoreException | NoSuchAlgorithmException e) { - LOG.error("Impossible to create temporary key store. Client authentication certs NOT loaded"); - LOG.debug("* Detailed Stacktrace:", e); - } catch (CertificateException e) { - LOG.error("Error when parsing client authentication certificate"); - LOG.debug("* Detailed Stacktrace:", e); - } catch (IOException e) { - LOG.error("Error when parsing client authentication certificate"); - LOG.debug("* Detailed Stacktrace:", e); - } - } - } + private static final Logger LOG = LoggerFactory.getLogger(BootCustomizationBean.class); + + @Autowired + private ConfigurationService configurationService; + + @Autowired + private X509AuthenticationProvider x509AuthenticationProvider; + + @Bean + public EmbeddedServletContainerFactory servletContainer() { + + TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory(); + factory.setPort(configurationService.getConfiguration().getGlobalConfiguration().getPort()); + + factory.setSessionTimeout(5, TimeUnit.MINUTES); + + factory.addConnectorCustomizers(new TomcatConnectorCustomizer() { + @Override + public void customize(Connector connector) { + + AbstractHttp11Protocol httpProtocol = (AbstractHttp11Protocol) connector.getProtocolHandler(); + httpProtocol.setCompression("on"); + httpProtocol.setMaxThreads(150); + + if (configurationService.getConfiguration().getGlobalConfiguration().isSecure()) { + + connector.setSecure(true); + connector.setScheme("https"); + connector.setAttribute("keystoreFile", "file:///" + + configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePath()); + connector.setAttribute("keystorePass", + configurationService.getConfiguration().getGlobalConfiguration().getSslKeystorePassword()); + connector.setAttribute("keystoreType", "PKCS12"); + connector.setAttribute("keyAlias", "1"); + connector.setAttribute("sslProtocol", "TLSv1.2"); + connector.setAttribute("sslEnabledProtocols", "+TLSv1.1,+TLSv1.2"); + connector.setAttribute("SSLEnabled", true); + connector.setAttribute("ciphers", + "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"); + connector.setAttribute("server", "Ident.io Server"); + configureTlsClientAuth(connector); + } + } + }); + return factory; + } + + private void configureTlsClientAuth(Connector connector) { + + List x509methods = configurationService.getConfiguration().getAuthMethodConfiguration() + .getX509AuthMethods(); + + if (x509methods != null) { + + try (FileOutputStream fos = new FileOutputStream( + configurationService.getConfiguration().getGlobalConfiguration().getWorkDirectory() + + "/identio-trust.jks")) { + + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); + + for (X509Certificate cert : x509AuthenticationProvider.getServerTrusts()) { + SecurityUtils.addCertificateToKeyStore(ks, cert, UUID.randomUUID().toString()); + } + + // As the keystore contains only public certs, the password here + // is not relevant + String trustPassword = UUID.randomUUID().toString(); + ks.store(fos, trustPassword.toCharArray()); + + connector.setAttribute("clientAuth", "want"); + connector.setAttribute("truststoreFile", + "file:///" + configurationService.getConfiguration().getGlobalConfiguration().getWorkDirectory() + + "/identio-trust.jks"); + connector.setAttribute("truststorePass", trustPassword); + connector.setAttribute("truststoreType", "JKS"); + + } catch (KeyStoreException | NoSuchAlgorithmException e) { + LOG.error("Impossible to create temporary key store. Client authentication certs NOT loaded"); + LOG.debug("* Detailed Stacktrace:", e); + } catch (CertificateException e) { + LOG.error("Error when parsing client authentication certificate"); + LOG.debug("* Detailed Stacktrace:", e); + } catch (IOException e) { + LOG.error("Error when parsing client authentication certificate"); + LOG.debug("* Detailed Stacktrace:", e); + } + } + } } \ No newline at end of file diff --git a/src/main/java/net/identio/server/boot/IdentioServerApplication.java b/src/main/java/net/identio/server/boot/IdentioServerApplication.java index 33aa08f..b0a6674 100644 --- a/src/main/java/net/identio/server/boot/IdentioServerApplication.java +++ b/src/main/java/net/identio/server/boot/IdentioServerApplication.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.boot; @@ -28,11 +29,11 @@ License, or (at your option) any later version. @SpringBootApplication @EnableAutoConfiguration(exclude = MongoAutoConfiguration.class) -@ComponentScan(basePackages = { "net.identio.server" }) +@ComponentScan(basePackages = {"net.identio.server"}) @EnableScheduling public class IdentioServerApplication { - public static void main(String[] args) { - SpringApplication.run(IdentioServerApplication.class, args); - } + public static void main(String[] args) { + SpringApplication.run(IdentioServerApplication.class, args); + } } diff --git a/src/main/java/net/identio/server/boot/ServletInitializer.java b/src/main/java/net/identio/server/boot/ServletInitializer.java index 868ad59..7ebb285 100644 --- a/src/main/java/net/identio/server/boot/ServletInitializer.java +++ b/src/main/java/net/identio/server/boot/ServletInitializer.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.boot; @@ -24,9 +25,9 @@ License, or (at your option) any later version. public class ServletInitializer extends SpringBootServletInitializer { - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(IdentioServerApplication.class); - } + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(IdentioServerApplication.class); + } } diff --git a/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java b/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java index a511758..f58b114 100644 --- a/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java +++ b/src/main/java/net/identio/server/boot/StaticResourceConfiguration.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.boot; @@ -31,26 +32,26 @@ License, or (at your option) any later version. @Configuration public class StaticResourceConfiguration extends WebMvcConfigurerAdapter { - @Autowired - private ConfigurationService configurationService; + @Autowired + private ConfigurationService configurationService; - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { - String resourceLocation = "file:" - + configurationService.getConfiguration().getGlobalConfiguration().getStaticResourcesPath(); + String resourceLocation = "file:" + + configurationService.getConfiguration().getGlobalConfiguration().getStaticResourcesPath(); - // Spring resource mapping is picky about the format of the path we - // provide it.. The trailing file separator IS important... - if (!resourceLocation.endsWith(File.separator)) { - resourceLocation = new StringBuilder(resourceLocation).append(File.separator).toString(); - } + // Spring resource mapping is picky about the format of the path we + // provide it.. The trailing file separator IS important... + if (!resourceLocation.endsWith(File.separator)) { + resourceLocation = new StringBuilder(resourceLocation).append(File.separator).toString(); + } - registry.addResourceHandler("/**").addResourceLocations(resourceLocation); - } + registry.addResourceHandler("/**").addResourceLocations(resourceLocation); + } - @Override - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/").setViewName("forward:/index.html"); - } + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/").setViewName("forward:/index.html"); + } } \ No newline at end of file diff --git a/src/main/java/net/identio/server/exceptions/AuthMethodNotAllowedException.java b/src/main/java/net/identio/server/exceptions/AuthMethodNotAllowedException.java index 41afe0f..6b4a898 100644 --- a/src/main/java/net/identio/server/exceptions/AuthMethodNotAllowedException.java +++ b/src/main/java/net/identio/server/exceptions/AuthMethodNotAllowedException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class AuthMethodNotAllowedException extends Exception { - private static final long serialVersionUID = 8995585261622747656L; + private static final long serialVersionUID = 8995585261622747656L; - public AuthMethodNotAllowedException(String s) { - super(s); - } + public AuthMethodNotAllowedException(String s) { + super(s); + } - public AuthMethodNotAllowedException(String s, Throwable e) { - super(s, e); - } + public AuthMethodNotAllowedException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/AuthenticationException.java b/src/main/java/net/identio/server/exceptions/AuthenticationException.java index d417746..8ef7838 100644 --- a/src/main/java/net/identio/server/exceptions/AuthenticationException.java +++ b/src/main/java/net/identio/server/exceptions/AuthenticationException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class AuthenticationException extends Exception { - private static final long serialVersionUID = 7980689067621954038L; + private static final long serialVersionUID = 7980689067621954038L; - public AuthenticationException(String s) { - super(s); - } + public AuthenticationException(String s) { + super(s); + } - public AuthenticationException(String s, Throwable e) { - super(s, e); - } + public AuthenticationException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/ConfigurationException.java b/src/main/java/net/identio/server/exceptions/ConfigurationException.java index 99be367..e58b46b 100644 --- a/src/main/java/net/identio/server/exceptions/ConfigurationException.java +++ b/src/main/java/net/identio/server/exceptions/ConfigurationException.java @@ -1,34 +1,35 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class ConfigurationException extends Exception { - private static final long serialVersionUID = 4255226680771267457L; + private static final long serialVersionUID = 4255226680771267457L; - public ConfigurationException(String s) { - super(s); - } + public ConfigurationException(String s) { + super(s); + } - public ConfigurationException(String s, Throwable e) { - super(s, e); - } + public ConfigurationException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/InitializationException.java b/src/main/java/net/identio/server/exceptions/InitializationException.java index 0fc07b4..51c4b07 100644 --- a/src/main/java/net/identio/server/exceptions/InitializationException.java +++ b/src/main/java/net/identio/server/exceptions/InitializationException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class InitializationException extends Exception { - private static final long serialVersionUID = 5040876591967204079L; + private static final long serialVersionUID = 5040876591967204079L; - public InitializationException(String s) { - super(s); - } + public InitializationException(String s) { + super(s); + } - public InitializationException(String s, Throwable e) { - super(s, e); - } + public InitializationException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java b/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java index ed798dd..ba6e781 100644 --- a/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java +++ b/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class NoAuthMethodFoundException extends Exception { - private static final long serialVersionUID = -7484071565697761702L; + private static final long serialVersionUID = -7484071565697761702L; - public NoAuthMethodFoundException(String s) { - super(s); - } + public NoAuthMethodFoundException(String s) { + super(s); + } - public NoAuthMethodFoundException(String s, Throwable e) { - super(s, e); - } + public NoAuthMethodFoundException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/SamlException.java b/src/main/java/net/identio/server/exceptions/SamlException.java index fc3b922..7d279c7 100644 --- a/src/main/java/net/identio/server/exceptions/SamlException.java +++ b/src/main/java/net/identio/server/exceptions/SamlException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class SamlException extends Exception { - private static final long serialVersionUID = 1738019933957155628L; + private static final long serialVersionUID = 1738019933957155628L; - public SamlException(String s) { - super(s); - } + public SamlException(String s) { + super(s); + } - public SamlException(String s, Throwable e) { - super(s, e); - } + public SamlException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/UnknownAuthLevelException.java b/src/main/java/net/identio/server/exceptions/UnknownAuthLevelException.java index 90fff1d..41760f5 100644 --- a/src/main/java/net/identio/server/exceptions/UnknownAuthLevelException.java +++ b/src/main/java/net/identio/server/exceptions/UnknownAuthLevelException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class UnknownAuthLevelException extends Exception { - private static final long serialVersionUID = -7696222698669688486L; + private static final long serialVersionUID = -7696222698669688486L; - public UnknownAuthLevelException(String s) { - super(s); - } + public UnknownAuthLevelException(String s) { + super(s); + } - public UnknownAuthLevelException(String s, Throwable e) { - super(s, e); - } + public UnknownAuthLevelException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/exceptions/UnknownAuthMethodException.java b/src/main/java/net/identio/server/exceptions/UnknownAuthMethodException.java index 094090d..425df8f 100644 --- a/src/main/java/net/identio/server/exceptions/UnknownAuthMethodException.java +++ b/src/main/java/net/identio/server/exceptions/UnknownAuthMethodException.java @@ -1,33 +1,34 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.exceptions; public class UnknownAuthMethodException extends Exception { - private static final long serialVersionUID = 8995585261622747656L; + private static final long serialVersionUID = 8995585261622747656L; - public UnknownAuthMethodException(String s) { - super(s); - } + public UnknownAuthMethodException(String s) { + super(s); + } - public UnknownAuthMethodException(String s, Throwable e) { - super(s, e); - } + public UnknownAuthMethodException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/model/AppAuthLevel.java b/src/main/java/net/identio/server/model/AppAuthLevel.java index 2f2013c..838d2f0 100644 --- a/src/main/java/net/identio/server/model/AppAuthLevel.java +++ b/src/main/java/net/identio/server/model/AppAuthLevel.java @@ -1,51 +1,52 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class AppAuthLevel { - private String appName; - private AuthLevel authLevel; - private String comparison; + private String appName; + private AuthLevel authLevel; + private String comparison; - public String getAppName() { - return appName; - } + public String getAppName() { + return appName; + } - public void setAppName(String appName) { - this.appName = appName; - } + public void setAppName(String appName) { + this.appName = appName; + } - public AuthLevel getAuthLevel() { - return authLevel; - } + public AuthLevel getAuthLevel() { + return authLevel; + } - public void setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - } + public void setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + } - public String getComparison() { - return comparison; - } + public String getComparison() { + return comparison; + } - public void setComparison(String comparison) { - this.comparison = comparison; - } + public void setComparison(String comparison) { + this.comparison = comparison; + } } diff --git a/src/main/java/net/identio/server/model/AuthLevel.java b/src/main/java/net/identio/server/model/AuthLevel.java index fc0802e..989975d 100644 --- a/src/main/java/net/identio/server/model/AuthLevel.java +++ b/src/main/java/net/identio/server/model/AuthLevel.java @@ -1,56 +1,57 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class AuthLevel { - private String name; - private String urn; - private int strength; + private String name; + private String urn; + private int strength; - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public String getUrn() { - return urn; - } + public String getUrn() { + return urn; + } - public void setUrn(String urn) { - this.urn = urn; - } + public void setUrn(String urn) { + this.urn = urn; + } - public int getStrength() { - return strength; - } + public int getStrength() { + return strength; + } - public void setStrength(int strength) { - this.strength = strength; - } + public void setStrength(int strength) { + this.strength = strength; + } - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof AuthLevel && this.name.equals(((AuthLevel) obj).name); - } + @Override + public boolean equals(Object obj) { + return obj != null && obj instanceof AuthLevel && this.name.equals(((AuthLevel) obj).name); + } } diff --git a/src/main/java/net/identio/server/model/AuthMethod.java b/src/main/java/net/identio/server/model/AuthMethod.java index 3758479..95572c5 100644 --- a/src/main/java/net/identio/server/model/AuthMethod.java +++ b/src/main/java/net/identio/server/model/AuthMethod.java @@ -1,71 +1,72 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public abstract class AuthMethod { - protected boolean explicit = true; + protected boolean explicit = true; - private String name; - private String logoFileName; - private AuthLevel authLevel; - protected String type; + private String name; + private String logoFileName; + private AuthLevel authLevel; + protected String type; - public boolean isExplicit() { - return explicit; - } + public boolean isExplicit() { + return explicit; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public String getLogoFileName() { - return logoFileName; - } + public String getLogoFileName() { + return logoFileName; + } - public void setLogoFileName(String logoFileName) { - this.logoFileName = logoFileName; - } + public void setLogoFileName(String logoFileName) { + this.logoFileName = logoFileName; + } - public AuthLevel getAuthLevel() { - return authLevel; - } + public AuthLevel getAuthLevel() { + return authLevel; + } - public void setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - } + public void setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + } - public String getType() { - return type; - } + public String getType() { + return type; + } - public void setType(String type) { - this.type = type; - } + public void setType(String type) { + this.type = type; + } - @Override - public boolean equals(Object obj) { - return obj != null && obj instanceof AuthMethod && this.name.equals(((AuthMethod) obj).name); - } + @Override + public boolean equals(Object obj) { + return obj != null && obj instanceof AuthMethod && this.name.equals(((AuthMethod) obj).name); + } } diff --git a/src/main/java/net/identio/server/model/AuthMethodConfiguration.java b/src/main/java/net/identio/server/model/AuthMethodConfiguration.java index 4941951..e1340e1 100644 --- a/src/main/java/net/identio/server/model/AuthMethodConfiguration.java +++ b/src/main/java/net/identio/server/model/AuthMethodConfiguration.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -24,71 +25,71 @@ License, or (at your option) any later version. public class AuthMethodConfiguration { - private List ldapAuthMethods; - private List x509AuthMethods; - private List radiusAuthMethods; - private List samlAuthMethods; - private List localAuthMethods; - private List authMethods; - - public List getLdapAuthMethods() { - return ldapAuthMethods; - } - - public void setLdapAuthMethods(List ldapAuthMethods) { - this.ldapAuthMethods = ldapAuthMethods; - } - - public List getX509AuthMethods() { - return x509AuthMethods; - } - - public void setX509AuthMethods(List x509AuthMethods) { - this.x509AuthMethods = x509AuthMethods; - } - - public List getRadiusAuthMethods() { - return radiusAuthMethods; - } - - public void setRadiusAuthMethods(List radiusAuthMethods) { - this.radiusAuthMethods = radiusAuthMethods; - } - - public List getSamlAuthMethods() { - return samlAuthMethods; - } - - public void setSamlAuthMethods(List samlAuthMethods) { - this.samlAuthMethods = samlAuthMethods; - } - - public List getLocalAuthMethods() { - return localAuthMethods; - } - - public void setLocalAuthMethods(List localAuthMethods) { - this.localAuthMethods = localAuthMethods; - } - - public List getAuthMethods() { - - if (authMethods == null) { - authMethods = new ArrayList(); - - if (ldapAuthMethods != null) - authMethods.addAll(ldapAuthMethods); - if (x509AuthMethods != null) - authMethods.addAll(x509AuthMethods); - if (radiusAuthMethods != null) - authMethods.addAll(radiusAuthMethods); - if (samlAuthMethods != null) - authMethods.addAll(samlAuthMethods); - if (localAuthMethods != null) - authMethods.addAll(localAuthMethods); - } - - return authMethods; - } + private List ldapAuthMethods; + private List x509AuthMethods; + private List radiusAuthMethods; + private List samlAuthMethods; + private List localAuthMethods; + private List authMethods; + + public List getLdapAuthMethods() { + return ldapAuthMethods; + } + + public void setLdapAuthMethods(List ldapAuthMethods) { + this.ldapAuthMethods = ldapAuthMethods; + } + + public List getX509AuthMethods() { + return x509AuthMethods; + } + + public void setX509AuthMethods(List x509AuthMethods) { + this.x509AuthMethods = x509AuthMethods; + } + + public List getRadiusAuthMethods() { + return radiusAuthMethods; + } + + public void setRadiusAuthMethods(List radiusAuthMethods) { + this.radiusAuthMethods = radiusAuthMethods; + } + + public List getSamlAuthMethods() { + return samlAuthMethods; + } + + public void setSamlAuthMethods(List samlAuthMethods) { + this.samlAuthMethods = samlAuthMethods; + } + + public List getLocalAuthMethods() { + return localAuthMethods; + } + + public void setLocalAuthMethods(List localAuthMethods) { + this.localAuthMethods = localAuthMethods; + } + + public List getAuthMethods() { + + if (authMethods == null) { + authMethods = new ArrayList(); + + if (ldapAuthMethods != null) + authMethods.addAll(ldapAuthMethods); + if (x509AuthMethods != null) + authMethods.addAll(x509AuthMethods); + if (radiusAuthMethods != null) + authMethods.addAll(radiusAuthMethods); + if (samlAuthMethods != null) + authMethods.addAll(samlAuthMethods); + if (localAuthMethods != null) + authMethods.addAll(localAuthMethods); + } + + return authMethods; + } } diff --git a/src/main/java/net/identio/server/model/AuthPolicyConfiguration.java b/src/main/java/net/identio/server/model/AuthPolicyConfiguration.java index d316bab..53ce5e5 100644 --- a/src/main/java/net/identio/server/model/AuthPolicyConfiguration.java +++ b/src/main/java/net/identio/server/model/AuthPolicyConfiguration.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -23,32 +24,32 @@ License, or (at your option) any later version. public class AuthPolicyConfiguration { - private List authLevels; - private AppAuthLevel defaultAuthLevel; - private List applicationSpecificAuthLevel; + private List authLevels; + private AppAuthLevel defaultAuthLevel; + private List applicationSpecificAuthLevel; - public List getAuthLevels() { - return authLevels; - } + public List getAuthLevels() { + return authLevels; + } - public void setAuthLevels(List authLevels) { - this.authLevels = authLevels; - } + public void setAuthLevels(List authLevels) { + this.authLevels = authLevels; + } - public AppAuthLevel getDefaultAuthLevel() { - return defaultAuthLevel; - } + public AppAuthLevel getDefaultAuthLevel() { + return defaultAuthLevel; + } - public void setDefaultAuthLevel(AppAuthLevel defaultAuthLevel) { - this.defaultAuthLevel = defaultAuthLevel; - } + public void setDefaultAuthLevel(AppAuthLevel defaultAuthLevel) { + this.defaultAuthLevel = defaultAuthLevel; + } - public List getApplicationSpecificAuthLevel() { - return applicationSpecificAuthLevel; - } + public List getApplicationSpecificAuthLevel() { + return applicationSpecificAuthLevel; + } - public void setApplicationSpecificAuthLevel(List applicationSpecificAuthLevel) { - this.applicationSpecificAuthLevel = applicationSpecificAuthLevel; - } + public void setApplicationSpecificAuthLevel(List applicationSpecificAuthLevel) { + this.applicationSpecificAuthLevel = applicationSpecificAuthLevel; + } } diff --git a/src/main/java/net/identio/server/model/AuthSession.java b/src/main/java/net/identio/server/model/AuthSession.java index ec12623..beeb398 100644 --- a/src/main/java/net/identio/server/model/AuthSession.java +++ b/src/main/java/net/identio/server/model/AuthSession.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -24,37 +25,37 @@ License, or (at your option) any later version. public class AuthSession { - private DateTime authInstant; - private AuthMethod authMethod; - private AuthLevel authLevel; + private DateTime authInstant; + private AuthMethod authMethod; + private AuthLevel authLevel; - public AuthSession(AuthMethod authMethod, AuthLevel authLevel) { - this.authInstant = new DateTime(DateTimeZone.UTC); - this.authMethod = authMethod; - this.authLevel = authLevel; - } + public AuthSession(AuthMethod authMethod, AuthLevel authLevel) { + this.authInstant = new DateTime(DateTimeZone.UTC); + this.authMethod = authMethod; + this.authLevel = authLevel; + } - public DateTime getAuthInstant() { - return authInstant; - } + public DateTime getAuthInstant() { + return authInstant; + } - public void setAuthInstant(DateTime authInstant) { - this.authInstant = authInstant; - } + public void setAuthInstant(DateTime authInstant) { + this.authInstant = authInstant; + } - public AuthMethod getAuthMethod() { - return authMethod; - } + public AuthMethod getAuthMethod() { + return authMethod; + } - public void setAuthMethod(AuthMethod authMethod) { - this.authMethod = authMethod; - } + public void setAuthMethod(AuthMethod authMethod) { + this.authMethod = authMethod; + } - public AuthLevel getAuthLevel() { - return authLevel; - } + public AuthLevel getAuthLevel() { + return authLevel; + } - public void setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - } + public void setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + } } diff --git a/src/main/java/net/identio/server/model/AuthorizationConfiguration.java b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java index 93d8294..0fc7b83 100644 --- a/src/main/java/net/identio/server/model/AuthorizationConfiguration.java +++ b/src/main/java/net/identio/server/model/AuthorizationConfiguration.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -23,13 +24,13 @@ License, or (at your option) any later version. public class AuthorizationConfiguration { - private List scopes; + private List scopes; - public List getScopes() { - return scopes; - } + public List getScopes() { + return scopes; + } - public void setScopes(List scopes) { - this.scopes = scopes; - } + public void setScopes(List scopes) { + this.scopes = scopes; + } } diff --git a/src/main/java/net/identio/server/model/AuthorizationScope.java b/src/main/java/net/identio/server/model/AuthorizationScope.java index 3df2df8..fc24cd7 100644 --- a/src/main/java/net/identio/server/model/AuthorizationScope.java +++ b/src/main/java/net/identio/server/model/AuthorizationScope.java @@ -1,59 +1,60 @@ /* - This file is part of Ident.io. + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package net.identio.server.model; - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY +public class AuthorizationScope { - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. + private String name; + private AuthLevel authLevel; + private int expirationTime; - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. + public String getName() { + return name; + } - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -package net.identio.server.model; + public void setName(String name) { + this.name = name; + } -public class AuthorizationScope { + public AuthLevel getAuthLevel() { + return authLevel; + } + + public void setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + } + + public int getExpirationTime() { + return expirationTime; + } + + public void setExpirationTime(int expirationTime) { + this.expirationTime = expirationTime; + } + + public AuthorizationScope getPublicCopy() { + AuthorizationScope response = new AuthorizationScope(); + response.setName(this.name); - private String name; - private AuthLevel authLevel; - private int expirationTime; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public AuthLevel getAuthLevel() { - return authLevel; - } - - public void setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - } - - public int getExpirationTime() { - return expirationTime; - } - - public void setExpirationTime(int expirationTime) { - this.expirationTime = expirationTime; - } - - public AuthorizationScope getPublicCopy() { - AuthorizationScope response = new AuthorizationScope(); - response.setName(this.name); - - return response; - } + return response; + } } diff --git a/src/main/java/net/identio/server/model/GlobalConfiguration.java b/src/main/java/net/identio/server/model/GlobalConfiguration.java index 82579da..e237724 100644 --- a/src/main/java/net/identio/server/model/GlobalConfiguration.java +++ b/src/main/java/net/identio/server/model/GlobalConfiguration.java @@ -1,96 +1,97 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class GlobalConfiguration { - private int port; - private boolean secure; - private String sslKeystorePath; - private String sslKeystorePassword; - private String signatureKeystorePath; - private String signatureKeystorePassword; - private String workDirectory; - private String staticResourcesPath; - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public boolean isSecure() { - return secure; - } - - public void setSecure(boolean secure) { - this.secure = secure; - } - - public String getSslKeystorePath() { - return sslKeystorePath; - } - - public void setSslKeystorePath(String sslKeystorePath) { - this.sslKeystorePath = sslKeystorePath; - } - - public String getSslKeystorePassword() { - return sslKeystorePassword; - } - - public void setSslKeystorePassword(String sslKeystorePassword) { - this.sslKeystorePassword = sslKeystorePassword; - } - - public String getSignatureKeystorePath() { - return signatureKeystorePath; - } - - public void setSignatureKeystorePath(String signatureKeystorePath) { - this.signatureKeystorePath = signatureKeystorePath; - } - - public String getSignatureKeystorePassword() { - return signatureKeystorePassword; - } - - public void setSignatureKeystorePassword(String signatureKeystorePassword) { - this.signatureKeystorePassword = signatureKeystorePassword; - } - - public String getWorkDirectory() { - return workDirectory; - } - - public void setWorkDirectory(String workDirectory) { - this.workDirectory = workDirectory; - } - - public String getStaticResourcesPath() { - return staticResourcesPath; - } - - public void setStaticResourcesPath(String staticResourcesPath) { - this.staticResourcesPath = staticResourcesPath; - } + private int port; + private boolean secure; + private String sslKeystorePath; + private String sslKeystorePassword; + private String signatureKeystorePath; + private String signatureKeystorePassword; + private String workDirectory; + private String staticResourcesPath; + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public boolean isSecure() { + return secure; + } + + public void setSecure(boolean secure) { + this.secure = secure; + } + + public String getSslKeystorePath() { + return sslKeystorePath; + } + + public void setSslKeystorePath(String sslKeystorePath) { + this.sslKeystorePath = sslKeystorePath; + } + + public String getSslKeystorePassword() { + return sslKeystorePassword; + } + + public void setSslKeystorePassword(String sslKeystorePassword) { + this.sslKeystorePassword = sslKeystorePassword; + } + + public String getSignatureKeystorePath() { + return signatureKeystorePath; + } + + public void setSignatureKeystorePath(String signatureKeystorePath) { + this.signatureKeystorePath = signatureKeystorePath; + } + + public String getSignatureKeystorePassword() { + return signatureKeystorePassword; + } + + public void setSignatureKeystorePassword(String signatureKeystorePassword) { + this.signatureKeystorePassword = signatureKeystorePassword; + } + + public String getWorkDirectory() { + return workDirectory; + } + + public void setWorkDirectory(String workDirectory) { + this.workDirectory = workDirectory; + } + + public String getStaticResourcesPath() { + return staticResourcesPath; + } + + public void setStaticResourcesPath(String staticResourcesPath) { + this.staticResourcesPath = staticResourcesPath; + } } diff --git a/src/main/java/net/identio/server/model/IdentioConfiguration.java b/src/main/java/net/identio/server/model/IdentioConfiguration.java index b7b2ed6..ca9f73e 100644 --- a/src/main/java/net/identio/server/model/IdentioConfiguration.java +++ b/src/main/java/net/identio/server/model/IdentioConfiguration.java @@ -1,87 +1,88 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class IdentioConfiguration { - private GlobalConfiguration globalConfiguration = new GlobalConfiguration(); - private SamlIdpConfiguration samlIdpConfiguration = new SamlIdpConfiguration(); - private SessionConfiguration sessionConfiguration = new SessionConfiguration(); - private AuthPolicyConfiguration authPolicyConfiguration = new AuthPolicyConfiguration(); - private AuthMethodConfiguration authMethodConfiguration = new AuthMethodConfiguration(); - private OAuthServerConfiguration oAuthServerConfiguration = new OAuthServerConfiguration(); - private AuthorizationConfiguration authorizationConfiguration = new AuthorizationConfiguration(); - - public GlobalConfiguration getGlobalConfiguration() { - return globalConfiguration; - } - - public void setGlobalConfiguration(GlobalConfiguration globalConfiguration) { - this.globalConfiguration = globalConfiguration; - } - - public SamlIdpConfiguration getSamlIdpConfiguration() { - return samlIdpConfiguration; - } - - public void setSamlIdpConfiguration(SamlIdpConfiguration samlIdpConfiguration) { - this.samlIdpConfiguration = samlIdpConfiguration; - } - - public SessionConfiguration getSessionConfiguration() { - return sessionConfiguration; - } - - public void setSessionConfiguration(SessionConfiguration sessionConfiguration) { - this.sessionConfiguration = sessionConfiguration; - } - - public AuthPolicyConfiguration getAuthPolicyConfiguration() { - return authPolicyConfiguration; - } - - public void setAuthPolicyConfiguration(AuthPolicyConfiguration authPolicyConfiguration) { - this.authPolicyConfiguration = authPolicyConfiguration; - } - - public AuthMethodConfiguration getAuthMethodConfiguration() { - return authMethodConfiguration; - } - - public void setAuthMethodConfiguration(AuthMethodConfiguration authMethodConfiguration) { - this.authMethodConfiguration = authMethodConfiguration; - } - - public OAuthServerConfiguration getoAuthServerConfiguration() { - return oAuthServerConfiguration; - } - - public void setoAuthServerConfiguration(OAuthServerConfiguration oAuthServerConfiguration) { - this.oAuthServerConfiguration = oAuthServerConfiguration; - } - - public AuthorizationConfiguration getAuthorizationConfiguration() { - return authorizationConfiguration; - } - - public void setAuthorizationConfiguration(AuthorizationConfiguration authorizationConfiguration) { - this.authorizationConfiguration = authorizationConfiguration; - } + private GlobalConfiguration globalConfiguration = new GlobalConfiguration(); + private SamlIdpConfiguration samlIdpConfiguration = new SamlIdpConfiguration(); + private SessionConfiguration sessionConfiguration = new SessionConfiguration(); + private AuthPolicyConfiguration authPolicyConfiguration = new AuthPolicyConfiguration(); + private AuthMethodConfiguration authMethodConfiguration = new AuthMethodConfiguration(); + private OAuthServerConfiguration oAuthServerConfiguration = new OAuthServerConfiguration(); + private AuthorizationConfiguration authorizationConfiguration = new AuthorizationConfiguration(); + + public GlobalConfiguration getGlobalConfiguration() { + return globalConfiguration; + } + + public void setGlobalConfiguration(GlobalConfiguration globalConfiguration) { + this.globalConfiguration = globalConfiguration; + } + + public SamlIdpConfiguration getSamlIdpConfiguration() { + return samlIdpConfiguration; + } + + public void setSamlIdpConfiguration(SamlIdpConfiguration samlIdpConfiguration) { + this.samlIdpConfiguration = samlIdpConfiguration; + } + + public SessionConfiguration getSessionConfiguration() { + return sessionConfiguration; + } + + public void setSessionConfiguration(SessionConfiguration sessionConfiguration) { + this.sessionConfiguration = sessionConfiguration; + } + + public AuthPolicyConfiguration getAuthPolicyConfiguration() { + return authPolicyConfiguration; + } + + public void setAuthPolicyConfiguration(AuthPolicyConfiguration authPolicyConfiguration) { + this.authPolicyConfiguration = authPolicyConfiguration; + } + + public AuthMethodConfiguration getAuthMethodConfiguration() { + return authMethodConfiguration; + } + + public void setAuthMethodConfiguration(AuthMethodConfiguration authMethodConfiguration) { + this.authMethodConfiguration = authMethodConfiguration; + } + + public OAuthServerConfiguration getoAuthServerConfiguration() { + return oAuthServerConfiguration; + } + + public void setoAuthServerConfiguration(OAuthServerConfiguration oAuthServerConfiguration) { + this.oAuthServerConfiguration = oAuthServerConfiguration; + } + + public AuthorizationConfiguration getAuthorizationConfiguration() { + return authorizationConfiguration; + } + + public void setAuthorizationConfiguration(AuthorizationConfiguration authorizationConfiguration) { + this.authorizationConfiguration = authorizationConfiguration; + } } diff --git a/src/main/java/net/identio/server/model/InboundRequest.java b/src/main/java/net/identio/server/model/InboundRequest.java index 9206f7a..1794821 100644 --- a/src/main/java/net/identio/server/model/InboundRequest.java +++ b/src/main/java/net/identio/server/model/InboundRequest.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.model; public interface InboundRequest { diff --git a/src/main/java/net/identio/server/model/LdapAuthMethod.java b/src/main/java/net/identio/server/model/LdapAuthMethod.java index 3a777c9..6971ff8 100644 --- a/src/main/java/net/identio/server/model/LdapAuthMethod.java +++ b/src/main/java/net/identio/server/model/LdapAuthMethod.java @@ -1,92 +1,93 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class LdapAuthMethod extends AuthMethod { - private String[] ldapUrl; - private String proxyUser; - private String proxyPassword; - private String baseDn; - private String userSearchFilter; - private String trustCert; - private LdapPoolConfig poolConfig; - - public LdapAuthMethod() { - this.type = "ldap"; - } - - public String[] getLdapUrl() { - return ldapUrl; - } - - public void setLdapUrl(String[] ldapUrl) { - this.ldapUrl = ldapUrl; - } - - public String getProxyUser() { - return proxyUser; - } - - public void setProxyUser(String proxyUser) { - this.proxyUser = proxyUser; - } - - public String getProxyPassword() { - return proxyPassword; - } - - public void setProxyPassword(String proxyPassword) { - this.proxyPassword = proxyPassword; - } - - public String getBaseDn() { - return baseDn; - } - - public void setBaseDn(String baseDn) { - this.baseDn = baseDn; - } - - public String getUserSearchFilter() { - return userSearchFilter; - } - - public void setUserSearchFilter(String userSearchFilter) { - this.userSearchFilter = userSearchFilter; - } - - public String getTrustCert() { - return trustCert; - } - - public void setTrustCert(String trustCert) { - this.trustCert = trustCert; - } - - public LdapPoolConfig getPoolConfig() { - return poolConfig; - } - - public void setPoolConfig(LdapPoolConfig poolConfig) { - this.poolConfig = poolConfig; - } + private String[] ldapUrl; + private String proxyUser; + private String proxyPassword; + private String baseDn; + private String userSearchFilter; + private String trustCert; + private LdapPoolConfig poolConfig; + + public LdapAuthMethod() { + this.type = "ldap"; + } + + public String[] getLdapUrl() { + return ldapUrl; + } + + public void setLdapUrl(String[] ldapUrl) { + this.ldapUrl = ldapUrl; + } + + public String getProxyUser() { + return proxyUser; + } + + public void setProxyUser(String proxyUser) { + this.proxyUser = proxyUser; + } + + public String getProxyPassword() { + return proxyPassword; + } + + public void setProxyPassword(String proxyPassword) { + this.proxyPassword = proxyPassword; + } + + public String getBaseDn() { + return baseDn; + } + + public void setBaseDn(String baseDn) { + this.baseDn = baseDn; + } + + public String getUserSearchFilter() { + return userSearchFilter; + } + + public void setUserSearchFilter(String userSearchFilter) { + this.userSearchFilter = userSearchFilter; + } + + public String getTrustCert() { + return trustCert; + } + + public void setTrustCert(String trustCert) { + this.trustCert = trustCert; + } + + public LdapPoolConfig getPoolConfig() { + return poolConfig; + } + + public void setPoolConfig(LdapPoolConfig poolConfig) { + this.poolConfig = poolConfig; + } } diff --git a/src/main/java/net/identio/server/model/LdapPoolConfig.java b/src/main/java/net/identio/server/model/LdapPoolConfig.java index fbf6228..91c6824 100644 --- a/src/main/java/net/identio/server/model/LdapPoolConfig.java +++ b/src/main/java/net/identio/server/model/LdapPoolConfig.java @@ -1,97 +1,98 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class LdapPoolConfig { - private int minIdleConnections = 4; - private int maxIdleConnections = 8; - private boolean testWhileIdle; - private boolean testOnBorrow; - private String testRequestFilter = "(objectclass=*)"; - private int timeBetweenEvictionRuns = 30; - private int numTestsPerEvictionRun = 4; - private int minEvictableIdleTime = -1; - - public int getMinIdleConnections() { - return minIdleConnections; - } - - public void setMinIdleConnections(int minIdleConnections) { - this.minIdleConnections = minIdleConnections; - } - - public int getMaxIdleConnections() { - return maxIdleConnections; - } - - public void setMaxIdleConnections(int maxIdleConnections) { - this.maxIdleConnections = maxIdleConnections; - } - - public boolean isTestWhileIdle() { - return testWhileIdle; - } - - public void setTestWhileIdle(boolean testWhileIdle) { - this.testWhileIdle = testWhileIdle; - } - - public boolean isTestOnBorrow() { - return testOnBorrow; - } - - public void setTestOnBorrow(boolean testOnBorrow) { - this.testOnBorrow = testOnBorrow; - } - - public String getTestRequestFilter() { - return testRequestFilter; - } - - public void setTestRequestFilter(String testRequestFilter) { - this.testRequestFilter = testRequestFilter; - } - - public int getTimeBetweenEvictionRuns() { - return timeBetweenEvictionRuns; - } - - public void setTimeBetweenEvictionRuns(int timeBetweenEvictionRuns) { - this.timeBetweenEvictionRuns = timeBetweenEvictionRuns; - } - - public int getNumTestsPerEvictionRun() { - return numTestsPerEvictionRun; - } - - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { - this.numTestsPerEvictionRun = numTestsPerEvictionRun; - } - - public int getMinEvictableIdleTime() { - return minEvictableIdleTime; - } - - public void setMinEvictableIdleTime(int minEvictableIdleTime) { - this.minEvictableIdleTime = minEvictableIdleTime; - } + private int minIdleConnections = 4; + private int maxIdleConnections = 8; + private boolean testWhileIdle; + private boolean testOnBorrow; + private String testRequestFilter = "(objectclass=*)"; + private int timeBetweenEvictionRuns = 30; + private int numTestsPerEvictionRun = 4; + private int minEvictableIdleTime = -1; + + public int getMinIdleConnections() { + return minIdleConnections; + } + + public void setMinIdleConnections(int minIdleConnections) { + this.minIdleConnections = minIdleConnections; + } + + public int getMaxIdleConnections() { + return maxIdleConnections; + } + + public void setMaxIdleConnections(int maxIdleConnections) { + this.maxIdleConnections = maxIdleConnections; + } + + public boolean isTestWhileIdle() { + return testWhileIdle; + } + + public void setTestWhileIdle(boolean testWhileIdle) { + this.testWhileIdle = testWhileIdle; + } + + public boolean isTestOnBorrow() { + return testOnBorrow; + } + + public void setTestOnBorrow(boolean testOnBorrow) { + this.testOnBorrow = testOnBorrow; + } + + public String getTestRequestFilter() { + return testRequestFilter; + } + + public void setTestRequestFilter(String testRequestFilter) { + this.testRequestFilter = testRequestFilter; + } + + public int getTimeBetweenEvictionRuns() { + return timeBetweenEvictionRuns; + } + + public void setTimeBetweenEvictionRuns(int timeBetweenEvictionRuns) { + this.timeBetweenEvictionRuns = timeBetweenEvictionRuns; + } + + public int getNumTestsPerEvictionRun() { + return numTestsPerEvictionRun; + } + + public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { + this.numTestsPerEvictionRun = numTestsPerEvictionRun; + } + + public int getMinEvictableIdleTime() { + return minEvictableIdleTime; + } + + public void setMinEvictableIdleTime(int minEvictableIdleTime) { + this.minEvictableIdleTime = minEvictableIdleTime; + } } diff --git a/src/main/java/net/identio/server/model/LocalAuthMethod.java b/src/main/java/net/identio/server/model/LocalAuthMethod.java index f9c8c5d..5ded931 100644 --- a/src/main/java/net/identio/server/model/LocalAuthMethod.java +++ b/src/main/java/net/identio/server/model/LocalAuthMethod.java @@ -1,37 +1,38 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class LocalAuthMethod extends AuthMethod { - private String userFilePath; + private String userFilePath; - public LocalAuthMethod() { - this.type = "local"; - } + public LocalAuthMethod() { + this.type = "local"; + } - public String getUserFilePath() { - return userFilePath; - } + public String getUserFilePath() { + return userFilePath; + } - public void setUserFilePath(String userFilePath) { - this.userFilePath = userFilePath; - } + public void setUserFilePath(String userFilePath) { + this.userFilePath = userFilePath; + } } diff --git a/src/main/java/net/identio/server/model/OAuthInboundRequest.java b/src/main/java/net/identio/server/model/OAuthInboundRequest.java index 7448065..d15991c 100644 --- a/src/main/java/net/identio/server/model/OAuthInboundRequest.java +++ b/src/main/java/net/identio/server/model/OAuthInboundRequest.java @@ -1,62 +1,83 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.model; import java.util.List; public class OAuthInboundRequest implements InboundRequest { - private String clientId; - private String responseType; - private String redirectUri; - private List scopes; - private String state; - - public OAuthInboundRequest(String clientId, String responseType, String redirectUri, List scopes, - String state) { - - this.clientId = clientId; - this.responseType = responseType; - this.redirectUri = redirectUri; - this.scopes = scopes; - this.state = state; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getResponseType() { - return responseType; - } - - public void setResponseType(String responseType) { - this.responseType = responseType; - } - - public String getRedirectUri() { - return redirectUri; - } - - public void setRedirectUri(String redirectUri) { - this.redirectUri = redirectUri; - } - - public List getScopes() { - return scopes; - } - - public void setScopes(List scopes) { - this.scopes = scopes; - } - - public String getState() { - return state; - } - - public void setState(String state) { - this.state = state; - } + private String clientId; + private String responseType; + private String redirectUri; + private List scopes; + private String state; + + public OAuthInboundRequest(String clientId, String responseType, String redirectUri, List scopes, + String state) { + + this.clientId = clientId; + this.responseType = responseType; + this.redirectUri = redirectUri; + this.scopes = scopes; + this.state = state; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public List getScopes() { + return scopes; + } + + public void setScopes(List scopes) { + this.scopes = scopes; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } } diff --git a/src/main/java/net/identio/server/model/OAuthServerConfiguration.java b/src/main/java/net/identio/server/model/OAuthServerConfiguration.java index cd63068..7308d48 100644 --- a/src/main/java/net/identio/server/model/OAuthServerConfiguration.java +++ b/src/main/java/net/identio/server/model/OAuthServerConfiguration.java @@ -1,34 +1,35 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class OAuthServerConfiguration { - private String clientFile; + private String clientFile; + + public String getClientFile() { + return clientFile; + } - public String getClientFile() { - return clientFile; - } + public void setClientFile(String clientFile) { + this.clientFile = clientFile; + } - public void setClientFile(String clientFile) { - this.clientFile = clientFile; - } - } diff --git a/src/main/java/net/identio/server/model/ProtocolType.java b/src/main/java/net/identio/server/model/ProtocolType.java index a27dc98..9f85c86 100644 --- a/src/main/java/net/identio/server/model/ProtocolType.java +++ b/src/main/java/net/identio/server/model/ProtocolType.java @@ -1,24 +1,25 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public enum ProtocolType { - SAML, OAUTH + SAML, OAUTH } diff --git a/src/main/java/net/identio/server/model/RadiusAuthMethod.java b/src/main/java/net/identio/server/model/RadiusAuthMethod.java index 816b5e8..01d7b6a 100644 --- a/src/main/java/net/identio/server/model/RadiusAuthMethod.java +++ b/src/main/java/net/identio/server/model/RadiusAuthMethod.java @@ -1,74 +1,75 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class RadiusAuthMethod extends AuthMethod { - private String[] radiusHost; - private int authPort = 1812; - private int accountPort = 1813; - private String sharedSecret; - private int timeout = 5000; + private String[] radiusHost; + private int authPort = 1812; + private int accountPort = 1813; + private String sharedSecret; + private int timeout = 5000; - public RadiusAuthMethod() { - this.type = "radius"; - } + public RadiusAuthMethod() { + this.type = "radius"; + } - public String[] getRadiusHost() { - return radiusHost; - } + public String[] getRadiusHost() { + return radiusHost; + } - public void setRadiusHost(String[] radiusHost) { - this.radiusHost = radiusHost; - } + public void setRadiusHost(String[] radiusHost) { + this.radiusHost = radiusHost; + } - public int getAuthPort() { - return authPort; - } + public int getAuthPort() { + return authPort; + } - public void setAuthPort(int authPort) { - this.authPort = authPort; - } + public void setAuthPort(int authPort) { + this.authPort = authPort; + } - public int getAccountPort() { - return accountPort; - } + public int getAccountPort() { + return accountPort; + } - public void setAccountPort(int accountPort) { - this.accountPort = accountPort; - } + public void setAccountPort(int accountPort) { + this.accountPort = accountPort; + } - public String getSharedSecret() { - return sharedSecret; - } + public String getSharedSecret() { + return sharedSecret; + } - public void setSharedSecret(String sharedSecret) { - this.sharedSecret = sharedSecret; - } + public void setSharedSecret(String sharedSecret) { + this.sharedSecret = sharedSecret; + } - public int getTimeout() { - return timeout; - } + public int getTimeout() { + return timeout; + } - public void setTimeout(int timeout) { - this.timeout = timeout; - } + public void setTimeout(int timeout) { + this.timeout = timeout; + } } diff --git a/src/main/java/net/identio/server/model/SamlAuthMap.java b/src/main/java/net/identio/server/model/SamlAuthMap.java index f46ef44..d706c2a 100644 --- a/src/main/java/net/identio/server/model/SamlAuthMap.java +++ b/src/main/java/net/identio/server/model/SamlAuthMap.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -23,23 +24,23 @@ License, or (at your option) any later version. public class SamlAuthMap { - private HashMap in; - private HashMap out; + private HashMap in; + private HashMap out; - public HashMap getIn() { - return in; - } + public HashMap getIn() { + return in; + } - public void setIn(HashMap in) { - this.in = in; - } + public void setIn(HashMap in) { + this.in = in; + } - public HashMap getOut() { - return out; - } + public HashMap getOut() { + return out; + } - public void setOut(HashMap out) { - this.out = out; - } + public void setOut(HashMap out) { + this.out = out; + } } diff --git a/src/main/java/net/identio/server/model/SamlAuthMethod.java b/src/main/java/net/identio/server/model/SamlAuthMethod.java index d95ce14..7d76d17 100644 --- a/src/main/java/net/identio/server/model/SamlAuthMethod.java +++ b/src/main/java/net/identio/server/model/SamlAuthMethod.java @@ -1,55 +1,56 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class SamlAuthMethod extends AuthMethod { - private String metadata; - private boolean certificateCheckEnabled; - private SamlAuthMap samlAuthMap; + private String metadata; + private boolean certificateCheckEnabled; + private SamlAuthMap samlAuthMap; - public SamlAuthMethod() { - this.type = "saml"; - } + public SamlAuthMethod() { + this.type = "saml"; + } - public String getMetadata() { - return metadata; - } + public String getMetadata() { + return metadata; + } - public void setMetadata(String metadata) { - this.metadata = metadata; - } + public void setMetadata(String metadata) { + this.metadata = metadata; + } - public boolean isCertificateCheckEnabled() { - return certificateCheckEnabled; - } + public boolean isCertificateCheckEnabled() { + return certificateCheckEnabled; + } - public void setCertificateCheckEnabled(boolean certificateCheckEnabled) { - this.certificateCheckEnabled = certificateCheckEnabled; - } + public void setCertificateCheckEnabled(boolean certificateCheckEnabled) { + this.certificateCheckEnabled = certificateCheckEnabled; + } - public SamlAuthMap getSamlAuthMap() { - return samlAuthMap; - } + public SamlAuthMap getSamlAuthMap() { + return samlAuthMap; + } - public void setSamlAuthMap(SamlAuthMap samlAuthMap) { - this.samlAuthMap = samlAuthMap; - } + public void setSamlAuthMap(SamlAuthMap samlAuthMap) { + this.samlAuthMap = samlAuthMap; + } } diff --git a/src/main/java/net/identio/server/model/SamlAuthentication.java b/src/main/java/net/identio/server/model/SamlAuthentication.java index 0212243..b73d216 100644 --- a/src/main/java/net/identio/server/model/SamlAuthentication.java +++ b/src/main/java/net/identio/server/model/SamlAuthentication.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -23,17 +24,17 @@ License, or (at your option) any later version. public class SamlAuthentication implements Authentication { - private String response; + private String response; - public SamlAuthentication(String response) { - this.setResponse(response); - } + public SamlAuthentication(String response) { + this.setResponse(response); + } - public String getResponse() { - return response; - } + public String getResponse() { + return response; + } - public void setResponse(String response) { - this.response = response; - } + public void setResponse(String response) { + this.response = response; + } } diff --git a/src/main/java/net/identio/server/model/SamlIdpConfiguration.java b/src/main/java/net/identio/server/model/SamlIdpConfiguration.java index fd26f1d..7514fc4 100644 --- a/src/main/java/net/identio/server/model/SamlIdpConfiguration.java +++ b/src/main/java/net/identio/server/model/SamlIdpConfiguration.java @@ -1,114 +1,115 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class SamlIdpConfiguration { - private String organizationName; - private String organizationDisplayName; - private String organizationUrl; - private String contactPersonSurname; - private String contactPersonEmail; - private boolean allowUnsecureRequests; - private boolean certificateCheckEnabled; - private int tokenValidityLength; - private int allowedTimeOffset; - private String spMetadataDirectory; - - public boolean isCertificateCheckEnabled() { - return certificateCheckEnabled; - } - - public void setCertificateCheckEnabled(boolean certificateCheckEnabled) { - this.certificateCheckEnabled = certificateCheckEnabled; - } - - public int getTokenValidityLength() { - return tokenValidityLength; - } - - public void setTokenValidityLength(int tokenValidityLength) { - this.tokenValidityLength = tokenValidityLength; - } - - public int getAllowedTimeOffset() { - return allowedTimeOffset; - } - - public void setAllowedTimeOffset(int allowedTimeOffset) { - this.allowedTimeOffset = allowedTimeOffset; - } - - public String getSpMetadataDirectory() { - return spMetadataDirectory; - } - - public void setSpMetadataDirectory(String spDirectory) { - this.spMetadataDirectory = spDirectory; - } - - public String getOrganizationName() { - return organizationName; - } - - public void setOrganizationName(String organizationName) { - this.organizationName = organizationName; - } - - public String getOrganizationDisplayName() { - return organizationDisplayName; - } - - public void setOrganizationDisplayName(String organizationDisplayName) { - this.organizationDisplayName = organizationDisplayName; - } - - public String getOrganizationUrl() { - return organizationUrl; - } - - public void setOrganizationUrl(String organizationUrl) { - this.organizationUrl = organizationUrl; - } - - public String getContactPersonSurname() { - return contactPersonSurname; - } - - public void setContactPersonSurname(String contactPersonSurname) { - this.contactPersonSurname = contactPersonSurname; - } - - public String getContactPersonEmail() { - return contactPersonEmail; - } - - public void setContactPersonEmail(String contactPersonEmail) { - this.contactPersonEmail = contactPersonEmail; - } - - public boolean isAllowUnsecureRequests() { - return allowUnsecureRequests; - } - - public void setAllowUnsecureRequests(boolean allowUnsecureRequests) { - this.allowUnsecureRequests = allowUnsecureRequests; - } + private String organizationName; + private String organizationDisplayName; + private String organizationUrl; + private String contactPersonSurname; + private String contactPersonEmail; + private boolean allowUnsecureRequests; + private boolean certificateCheckEnabled; + private int tokenValidityLength; + private int allowedTimeOffset; + private String spMetadataDirectory; + + public boolean isCertificateCheckEnabled() { + return certificateCheckEnabled; + } + + public void setCertificateCheckEnabled(boolean certificateCheckEnabled) { + this.certificateCheckEnabled = certificateCheckEnabled; + } + + public int getTokenValidityLength() { + return tokenValidityLength; + } + + public void setTokenValidityLength(int tokenValidityLength) { + this.tokenValidityLength = tokenValidityLength; + } + + public int getAllowedTimeOffset() { + return allowedTimeOffset; + } + + public void setAllowedTimeOffset(int allowedTimeOffset) { + this.allowedTimeOffset = allowedTimeOffset; + } + + public String getSpMetadataDirectory() { + return spMetadataDirectory; + } + + public void setSpMetadataDirectory(String spDirectory) { + this.spMetadataDirectory = spDirectory; + } + + public String getOrganizationName() { + return organizationName; + } + + public void setOrganizationName(String organizationName) { + this.organizationName = organizationName; + } + + public String getOrganizationDisplayName() { + return organizationDisplayName; + } + + public void setOrganizationDisplayName(String organizationDisplayName) { + this.organizationDisplayName = organizationDisplayName; + } + + public String getOrganizationUrl() { + return organizationUrl; + } + + public void setOrganizationUrl(String organizationUrl) { + this.organizationUrl = organizationUrl; + } + + public String getContactPersonSurname() { + return contactPersonSurname; + } + + public void setContactPersonSurname(String contactPersonSurname) { + this.contactPersonSurname = contactPersonSurname; + } + + public String getContactPersonEmail() { + return contactPersonEmail; + } + + public void setContactPersonEmail(String contactPersonEmail) { + this.contactPersonEmail = contactPersonEmail; + } + + public boolean isAllowUnsecureRequests() { + return allowUnsecureRequests; + } + + public void setAllowUnsecureRequests(boolean allowUnsecureRequests) { + this.allowUnsecureRequests = allowUnsecureRequests; + } } diff --git a/src/main/java/net/identio/server/model/SamlInboundRequest.java b/src/main/java/net/identio/server/model/SamlInboundRequest.java index 3c71a56..64f4009 100644 --- a/src/main/java/net/identio/server/model/SamlInboundRequest.java +++ b/src/main/java/net/identio/server/model/SamlInboundRequest.java @@ -1,89 +1,90 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class SamlInboundRequest implements InboundRequest { - private String binding; - private String serializedRequest; - private String signatureValue; - private String signedInfo; - private String signatureAlgorithm; - private String relayState; - - public SamlInboundRequest(String binding, String serializedRequest, String signatureValue, String signedInfo, - String signatureAlgorithm, String relayState) { - this.binding = binding; - this.serializedRequest = serializedRequest; - this.signatureValue = signatureValue; - this.signedInfo = signedInfo; - this.signatureAlgorithm = signatureAlgorithm; - this.relayState = relayState; - } - - public String getBinding() { - return binding; - } - - public void setBinding(String binding) { - this.binding = binding; - } - - public String getSerializedRequest() { - return serializedRequest; - } - - public void setSerializedRequest(String serializedRequest) { - this.serializedRequest = serializedRequest; - } - - public String getSignatureValue() { - return signatureValue; - } - - public void setSignatureValue(String signatureValue) { - this.signatureValue = signatureValue; - } - - public String getSignedInfo() { - return signedInfo; - } - - public void setSignedInfo(String signedInfo) { - this.signedInfo = signedInfo; - } - - public String getSignatureAlgorithm() { - return signatureAlgorithm; - } - - public void setSignatureAlgorithm(String signatureAlgorithm) { - this.signatureAlgorithm = signatureAlgorithm; - } - - public String getRelayState() { - return relayState; - } - - public void setRelayState(String relayState) { - this.relayState = relayState; - } + private String binding; + private String serializedRequest; + private String signatureValue; + private String signedInfo; + private String signatureAlgorithm; + private String relayState; + + public SamlInboundRequest(String binding, String serializedRequest, String signatureValue, String signedInfo, + String signatureAlgorithm, String relayState) { + this.binding = binding; + this.serializedRequest = serializedRequest; + this.signatureValue = signatureValue; + this.signedInfo = signedInfo; + this.signatureAlgorithm = signatureAlgorithm; + this.relayState = relayState; + } + + public String getBinding() { + return binding; + } + + public void setBinding(String binding) { + this.binding = binding; + } + + public String getSerializedRequest() { + return serializedRequest; + } + + public void setSerializedRequest(String serializedRequest) { + this.serializedRequest = serializedRequest; + } + + public String getSignatureValue() { + return signatureValue; + } + + public void setSignatureValue(String signatureValue) { + this.signatureValue = signatureValue; + } + + public String getSignedInfo() { + return signedInfo; + } + + public void setSignedInfo(String signedInfo) { + this.signedInfo = signedInfo; + } + + public String getSignatureAlgorithm() { + return signatureAlgorithm; + } + + public void setSignatureAlgorithm(String signatureAlgorithm) { + this.signatureAlgorithm = signatureAlgorithm; + } + + public String getRelayState() { + return relayState; + } + + public void setRelayState(String relayState) { + this.relayState = relayState; + } } diff --git a/src/main/java/net/identio/server/model/SessionConfiguration.java b/src/main/java/net/identio/server/model/SessionConfiguration.java index 4f59e22..2bcf731 100644 --- a/src/main/java/net/identio/server/model/SessionConfiguration.java +++ b/src/main/java/net/identio/server/model/SessionConfiguration.java @@ -1,42 +1,43 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class SessionConfiguration { - private String type; - private int duration = 60; + private String type; + private int duration = 60; - public String getType() { - return type; - } + public String getType() { + return type; + } - public void setType(String type) { - this.type = type; - } + public void setType(String type) { + this.type = type; + } - public int getDuration() { - return duration; - } + public int getDuration() { + return duration; + } - public void setDuration(int duration) { - this.duration = duration; - } + public void setDuration(int duration) { + this.duration = duration; + } } diff --git a/src/main/java/net/identio/server/model/UserSession.java b/src/main/java/net/identio/server/model/UserSession.java index b5a91df..4de4405 100644 --- a/src/main/java/net/identio/server/model/UserSession.java +++ b/src/main/java/net/identio/server/model/UserSession.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; @@ -24,49 +25,49 @@ License, or (at your option) any later version. public class UserSession { - private String id; - private String userId; - private ArrayList authSessions = new ArrayList<>(); - private HashSet validatedAuthMethods = new HashSet<>(); + private String id; + private String userId; + private ArrayList authSessions = new ArrayList<>(); + private HashSet validatedAuthMethods = new HashSet<>(); - public String getId() { - return id; - } + public String getId() { + return id; + } - public void setId(String id) { - this.id = id; - } + public void setId(String id) { + this.id = id; + } - public String getUserId() { - return userId; - } + public String getUserId() { + return userId; + } - public void setUserId(String userId) { - this.userId = userId; - } + public void setUserId(String userId) { + this.userId = userId; + } - public ArrayList getAuthSessions() { - return authSessions; - } + public ArrayList getAuthSessions() { + return authSessions; + } - public void setAuthSessions(ArrayList authSessions) { - this.authSessions = authSessions; - } + public void setAuthSessions(ArrayList authSessions) { + this.authSessions = authSessions; + } - public HashSet getValidatedAuthMethods() { - return validatedAuthMethods; - } + public HashSet getValidatedAuthMethods() { + return validatedAuthMethods; + } - public void setValidatedAuthMethods(HashSet validatedAuthMethods) { - this.validatedAuthMethods = validatedAuthMethods; - } + public void setValidatedAuthMethods(HashSet validatedAuthMethods) { + this.validatedAuthMethods = validatedAuthMethods; + } - public AuthSession addAuthSession(String userId, AuthMethod authMethod, AuthLevel authLevel) { - AuthSession authSession = new AuthSession(authMethod, authLevel); - this.userId = userId; - this.authSessions.add(authSession); - this.validatedAuthMethods.add(authMethod); + public AuthSession addAuthSession(String userId, AuthMethod authMethod, AuthLevel authLevel) { + AuthSession authSession = new AuthSession(authMethod, authLevel); + this.userId = userId; + this.authSessions.add(authSession); + this.validatedAuthMethods.add(authMethod); - return authSession; - } + return authSession; + } } diff --git a/src/main/java/net/identio/server/model/X509AuthMethod.java b/src/main/java/net/identio/server/model/X509AuthMethod.java index a513163..cd3d583 100644 --- a/src/main/java/net/identio/server/model/X509AuthMethod.java +++ b/src/main/java/net/identio/server/model/X509AuthMethod.java @@ -1,118 +1,119 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.model; public class X509AuthMethod extends AuthMethod { - private String uidExpression; - private String conditionExpression; - private String security; - private boolean apacheFix; - private String clientCertTrust; - private String certHeaderName; - private String securityHeaderName; - private String sharedSecret; - private String proxyCertDn; - private String proxyCertTrust; - - public X509AuthMethod() { - this.explicit = false; - } - - public String getUidExpression() { - return uidExpression; - } - - public void setUidExpression(String uidExpression) { - this.uidExpression = uidExpression; - } - - public String getConditionExpression() { - return conditionExpression; - } - - public void setConditionExpression(String conditionExpression) { - this.conditionExpression = conditionExpression; - } - - public String getSecurity() { - return security; - } - - public void setSecurity(String security) { - this.security = security; - } - - public boolean isApacheFix() { - return apacheFix; - } - - public void setApacheFix(boolean apacheFix) { - this.apacheFix = apacheFix; - } - - public String getClientCertTrust() { - return clientCertTrust; - } - - public void setClientCertTrust(String clientCertTrust) { - this.clientCertTrust = clientCertTrust; - } - - public String getCertHeaderName() { - return certHeaderName; - } - - public void setCertHeaderName(String certHeaderName) { - this.certHeaderName = certHeaderName; - } - - public String getSecurityHeaderName() { - return securityHeaderName; - } - - public void setSecurityHeaderName(String securityHeaderName) { - this.securityHeaderName = securityHeaderName; - } - - public String getSharedSecret() { - return sharedSecret; - } - - public void setSharedSecret(String sharedSecret) { - this.sharedSecret = sharedSecret; - } - - public String getProxyCertDn() { - return proxyCertDn; - } - - public void setProxyCertDn(String proxyCertDn) { - this.proxyCertDn = proxyCertDn; - } - - public String getProxyCertTrust() { - return proxyCertTrust; - } - - public void setProxyCertTrust(String proxyCertTrust) { - this.proxyCertTrust = proxyCertTrust; - } + private String uidExpression; + private String conditionExpression; + private String security; + private boolean apacheFix; + private String clientCertTrust; + private String certHeaderName; + private String securityHeaderName; + private String sharedSecret; + private String proxyCertDn; + private String proxyCertTrust; + + public X509AuthMethod() { + this.explicit = false; + } + + public String getUidExpression() { + return uidExpression; + } + + public void setUidExpression(String uidExpression) { + this.uidExpression = uidExpression; + } + + public String getConditionExpression() { + return conditionExpression; + } + + public void setConditionExpression(String conditionExpression) { + this.conditionExpression = conditionExpression; + } + + public String getSecurity() { + return security; + } + + public void setSecurity(String security) { + this.security = security; + } + + public boolean isApacheFix() { + return apacheFix; + } + + public void setApacheFix(boolean apacheFix) { + this.apacheFix = apacheFix; + } + + public String getClientCertTrust() { + return clientCertTrust; + } + + public void setClientCertTrust(String clientCertTrust) { + this.clientCertTrust = clientCertTrust; + } + + public String getCertHeaderName() { + return certHeaderName; + } + + public void setCertHeaderName(String certHeaderName) { + this.certHeaderName = certHeaderName; + } + + public String getSecurityHeaderName() { + return securityHeaderName; + } + + public void setSecurityHeaderName(String securityHeaderName) { + this.securityHeaderName = securityHeaderName; + } + + public String getSharedSecret() { + return sharedSecret; + } + + public void setSharedSecret(String sharedSecret) { + this.sharedSecret = sharedSecret; + } + + public String getProxyCertDn() { + return proxyCertDn; + } + + public void setProxyCertDn(String proxyCertDn) { + this.proxyCertDn = proxyCertDn; + } + + public String getProxyCertTrust() { + return proxyCertTrust; + } + + public void setProxyCertTrust(String proxyCertTrust) { + this.proxyCertTrust = proxyCertTrust; + } } diff --git a/src/main/java/net/identio/server/mvc/common/AuthentController.java b/src/main/java/net/identio/server/mvc/common/AuthentController.java index a8b8054..d1db698 100644 --- a/src/main/java/net/identio/server/mvc/common/AuthentController.java +++ b/src/main/java/net/identio/server/mvc/common/AuthentController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; diff --git a/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java b/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java index 5fac9df..9dbff2e 100644 --- a/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java +++ b/src/main/java/net/identio/server/mvc/common/DefaultErrorController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; @@ -26,16 +27,16 @@ License, or (at your option) any later version. @Controller public class DefaultErrorController implements ErrorController { - private static final String PATH = "/error"; + private static final String PATH = "/error"; - @RequestMapping(value = PATH) - public String displayErrorPage(String errorId) { + @RequestMapping(value = PATH) + public String displayErrorPage(String errorId) { - return "redirect:/#!/error/" + (errorId != null ? errorId : ""); - } + return "redirect:/#!/error/" + (errorId != null ? errorId : ""); + } - public String getErrorPath() { - return PATH; - } + public String getErrorPath() { + return PATH; + } } diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index 218ce72..6050d80 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; @@ -30,22 +31,22 @@ License, or (at your option) any later version. @ControllerAdvice public class GlobalControllerExceptionHandler { - @Autowired - private DefaultErrorController errorController; + @Autowired + private DefaultErrorController errorController; - @ExceptionHandler(ServerException.class) - public String handleServerException(ServerException e) { - return errorController.displayErrorPage(e.getMessage()); - } + @ExceptionHandler(ServerException.class) + public String handleServerException(ServerException e) { + return errorController.displayErrorPage(e.getMessage()); + } - @ExceptionHandler(ValidationException.class) - public String handleValidationException(ValidationException e) { - return errorController.displayErrorPage(e.getMessage()); - } + @ExceptionHandler(ValidationException.class) + public String handleValidationException(ValidationException e) { + return errorController.displayErrorPage(e.getMessage()); + } - @ExceptionHandler(WebSecurityException.class) - public String handleWebSecurityException(WebSecurityException e) { - return errorController.displayErrorPage(e.getMessage()); - } + @ExceptionHandler(WebSecurityException.class) + public String handleWebSecurityException(WebSecurityException e) { + return errorController.displayErrorPage(e.getMessage()); + } } diff --git a/src/main/java/net/identio/server/mvc/common/LogoController.java b/src/main/java/net/identio/server/mvc/common/LogoController.java index 9d19a41..6c4a8c4 100644 --- a/src/main/java/net/identio/server/mvc/common/LogoController.java +++ b/src/main/java/net/identio/server/mvc/common/LogoController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; @@ -41,50 +42,50 @@ License, or (at your option) any later version. @Controller public class LogoController { - private static final Logger LOG = LoggerFactory.getLogger(LogoController.class); + private static final Logger LOG = LoggerFactory.getLogger(LogoController.class); - @Autowired - private AuthPolicyService authPolicyService; + @Autowired + private AuthPolicyService authPolicyService; - @RequestMapping(value = "/logo/{authMethodName}", method = RequestMethod.GET) - @ResponseBody - public void getLogo(@PathVariable("authMethodName") String authMethodName, HttpServletResponse response) { + @RequestMapping(value = "/logo/{authMethodName}", method = RequestMethod.GET) + @ResponseBody + public void getLogo(@PathVariable("authMethodName") String authMethodName, HttpServletResponse response) { - String fileName = authPolicyService.getLogo(authMethodName); + String fileName = authPolicyService.getLogo(authMethodName); - if (fileName == null) { - response.setStatus(HttpStatus.NOT_FOUND.value()); - return; - } + if (fileName == null) { + response.setStatus(HttpStatus.NOT_FOUND.value()); + return; + } - File file = new File(fileName); + File file = new File(fileName); - HttpHeaders header = new HttpHeaders(); - header.setContentLength(file.length()); + HttpHeaders header = new HttpHeaders(); + header.setContentLength(file.length()); - if (fileName.endsWith(".png")) { - header.setContentType(MediaType.IMAGE_PNG); - } - if (fileName.endsWith(".jpg")) { - header.setContentType(MediaType.IMAGE_JPEG); - } + if (fileName.endsWith(".png")) { + header.setContentType(MediaType.IMAGE_PNG); + } + if (fileName.endsWith(".jpg")) { + header.setContentType(MediaType.IMAGE_JPEG); + } - try (FileInputStream is = new FileInputStream(file)) { + try (FileInputStream is = new FileInputStream(file)) { - byte[] buf = new byte[2048]; - ServletOutputStream os = response.getOutputStream(); + byte[] buf = new byte[2048]; + ServletOutputStream os = response.getOutputStream(); - while (is.read(buf) != -1) { - os.write(buf); - } + while (is.read(buf) != -1) { + os.write(buf); + } - response.flushBuffer(); - } catch (IOException e) { - LOG.error("Error when accessing logo file {}: {}", fileName, e.getMessage()); - LOG.debug("* Detailed stacktrace:", e); + response.flushBuffer(); + } catch (IOException e) { + LOG.error("Error when accessing logo file {}: {}", fileName, e.getMessage()); + LOG.debug("* Detailed stacktrace:", e); - response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); - return; - } - } + response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); + return; + } + } } diff --git a/src/main/java/net/identio/server/mvc/common/LogoutController.java b/src/main/java/net/identio/server/mvc/common/LogoutController.java index 25d45bc..59d298e 100644 --- a/src/main/java/net/identio/server/mvc/common/LogoutController.java +++ b/src/main/java/net/identio/server/mvc/common/LogoutController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; @@ -31,18 +32,18 @@ License, or (at your option) any later version. @Controller public class LogoutController { - private static final Logger LOG = LoggerFactory.getLogger(LogoutController.class); + private static final Logger LOG = LoggerFactory.getLogger(LogoutController.class); - @Autowired - private UserSessionService userSessionService; + @Autowired + private UserSessionService userSessionService; - @RequestMapping(value = "/logout", method = RequestMethod.GET) - public String logout(@CookieValue("identioSession") String sessionId) { + @RequestMapping(value = "/logout", method = RequestMethod.GET) + public String logout(@CookieValue("identioSession") String sessionId) { - LOG.info("Received logout request for session {}", sessionId); + LOG.info("Received logout request for session {}", sessionId); - userSessionService.removeUserSession(sessionId); + userSessionService.removeUserSession(sessionId); - return "redirect:/#/logout"; - } + return "redirect:/#/logout"; + } } diff --git a/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java index 0b4c422..2559aaf 100644 --- a/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java +++ b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.common; @@ -64,8 +65,7 @@ public String checkTransparentAuthentication(HttpServletRequest httpRequest, Htt if (clientAuthCerts != null || userCert != null && sharedSecret != null) { authentication = new X509Authentication((X509Certificate[]) clientAuthCerts, userCert, sharedSecret); - } - else { + } else { return redirectToAuthenticationPage(httpResponse, sessionId, transactionId); } diff --git a/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java b/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java index d01c8fa..65b5388 100644 --- a/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/ApiErrorResponse.java @@ -26,17 +26,17 @@ @JsonInclude(Include.NON_NULL) public class ApiErrorResponse { - private String errorCode; + private String errorCode; - public ApiErrorResponse(String errorCode) { - this.errorCode = errorCode; - } + public ApiErrorResponse(String errorCode) { + this.errorCode = errorCode; + } - public String getErrorCode() { - return errorCode; - } + public String getErrorCode() { + return errorCode; + } - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; - } + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } } diff --git a/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java b/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java index 32d161a..f08fde6 100644 --- a/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthMethodResponse.java @@ -26,25 +26,25 @@ @JsonInclude(Include.NON_NULL) public class AuthMethodResponse { - private String name; - private String type; - - public String getName() { - return name; - } - - public AuthMethodResponse setName(String name) { - this.name = name; - return this; - } - - public String getType() { - return type; - } - - public AuthMethodResponse setType(String type) { - this.type = type; - return this; - } + private String name; + private String type; + + public String getName() { + return name; + } + + public AuthMethodResponse setName(String name) { + this.name = name; + return this; + } + + public String getType() { + return type; + } + + public AuthMethodResponse setType(String type) { + this.type = type; + return this; + } } diff --git a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java index e45eb69..ff37040 100644 --- a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitRequest.java @@ -26,45 +26,45 @@ @JsonInclude(Include.NON_NULL) public class AuthSubmitRequest { - private String method; - private String login; - private String password; - private String challengeResponse; + private String method; + private String login; + private String password; + private String challengeResponse; - public String getMethod() { - return method; - } + public String getMethod() { + return method; + } - public AuthSubmitRequest setMethod(String method) { - this.method = method; - return this; - } + public AuthSubmitRequest setMethod(String method) { + this.method = method; + return this; + } - public String getLogin() { - return login; - } + public String getLogin() { + return login; + } - public AuthSubmitRequest setLogin(String login) { - this.login = login; - return this; - } + public AuthSubmitRequest setLogin(String login) { + this.login = login; + return this; + } - public String getPassword() { - return password; - } + public String getPassword() { + return password; + } - public AuthSubmitRequest setPassword(String password) { - this.password = password; - return this; - } + public AuthSubmitRequest setPassword(String password) { + this.password = password; + return this; + } - public String getChallengeResponse() { - return challengeResponse; - } + public String getChallengeResponse() { + return challengeResponse; + } - public AuthSubmitRequest setChallengeResponse(String challengeResponse) { - this.challengeResponse = challengeResponse; - return this; - } + public AuthSubmitRequest setChallengeResponse(String challengeResponse) { + this.challengeResponse = challengeResponse; + return this; + } } diff --git a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java index 1f9cb4c..6fedb08 100644 --- a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java @@ -27,85 +27,85 @@ @JsonInclude(Include.NON_NULL) public class AuthSubmitResponse { - private ApiResponseStatus status; - private String errorStatus; - private String destinationUrl; - private String relayState; - private String data; - private ProtocolType protocolType; - private String challengeType; - private String challengeValue; - - public ApiResponseStatus getStatus() { - return status; - } - - public AuthSubmitResponse setStatus(ApiResponseStatus status) { - this.status = status; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public AuthSubmitResponse setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public String getDestinationUrl() { - return destinationUrl; - } - - public AuthSubmitResponse setDestinationUrl(String destinationUrl) { - this.destinationUrl = destinationUrl; - return this; - } - - public String getRelayState() { - return relayState; - } - - public AuthSubmitResponse setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getData() { - return data; - } - - public AuthSubmitResponse setData(String data) { - this.data = data; - return this; - } - - public ProtocolType getProtocolType() { - return protocolType; - } - - public AuthSubmitResponse setProtocolType(ProtocolType protocolType) { - this.protocolType = protocolType; - return this; - } - - public String getChallengeType() { - return challengeType; - } - - public AuthSubmitResponse setChallengeType(String challengeType) { - this.challengeType = challengeType; - return this; - } - - public String getChallengeValue() { - return challengeValue; - } - - public AuthSubmitResponse setChallengeValue(String challengeValue) { - this.challengeValue = challengeValue; - return this; - } + private ApiResponseStatus status; + private String errorStatus; + private String destinationUrl; + private String relayState; + private String data; + private ProtocolType protocolType; + private String challengeType; + private String challengeValue; + + public ApiResponseStatus getStatus() { + return status; + } + + public AuthSubmitResponse setStatus(ApiResponseStatus status) { + this.status = status; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public AuthSubmitResponse setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public String getDestinationUrl() { + return destinationUrl; + } + + public AuthSubmitResponse setDestinationUrl(String destinationUrl) { + this.destinationUrl = destinationUrl; + return this; + } + + public String getRelayState() { + return relayState; + } + + public AuthSubmitResponse setRelayState(String relayState) { + this.relayState = relayState; + return this; + } + + public String getData() { + return data; + } + + public AuthSubmitResponse setData(String data) { + this.data = data; + return this; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public AuthSubmitResponse setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + return this; + } + + public String getChallengeType() { + return challengeType; + } + + public AuthSubmitResponse setChallengeType(String challengeType) { + this.challengeType = challengeType; + return this; + } + + public String getChallengeValue() { + return challengeValue; + } + + public AuthSubmitResponse setChallengeValue(String challengeValue) { + this.challengeValue = challengeValue; + return this; + } } diff --git a/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java b/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java index c0338cd..5885990 100644 --- a/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/LaunchSamlAuthenticationResponse.java @@ -26,74 +26,74 @@ @JsonInclude(Include.NON_NULL) public class LaunchSamlAuthenticationResponse { - private String destinationUrl; - private String errorStatus; - private String binding; - private String relayState; - private String samlRequest; - private String sigAlg; - private String signature; - - public String getDestinationUrl() { - return destinationUrl; - } - - public LaunchSamlAuthenticationResponse setDestinationUrl(String destinationUrl) { - this.destinationUrl = destinationUrl; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public LaunchSamlAuthenticationResponse setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public String getBinding() { - return binding; - } - - public LaunchSamlAuthenticationResponse setBinding(String binding) { - this.binding = binding; - return this; - } - - public String getRelayState() { - return relayState; - } - - public LaunchSamlAuthenticationResponse setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getSamlRequest() { - return samlRequest; - } - - public LaunchSamlAuthenticationResponse setSamlRequest(String samlRequest) { - this.samlRequest = samlRequest; - return this; - } - - public String getSigAlg() { - return sigAlg; - } - - public LaunchSamlAuthenticationResponse setSigAlg(String sigAlg) { - this.sigAlg = sigAlg; - return this; - } - - public String getSignature() { - return signature; - } - - public LaunchSamlAuthenticationResponse setSignature(String signature) { - this.signature = signature; - return this; - } + private String destinationUrl; + private String errorStatus; + private String binding; + private String relayState; + private String samlRequest; + private String sigAlg; + private String signature; + + public String getDestinationUrl() { + return destinationUrl; + } + + public LaunchSamlAuthenticationResponse setDestinationUrl(String destinationUrl) { + this.destinationUrl = destinationUrl; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public LaunchSamlAuthenticationResponse setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public String getBinding() { + return binding; + } + + public LaunchSamlAuthenticationResponse setBinding(String binding) { + this.binding = binding; + return this; + } + + public String getRelayState() { + return relayState; + } + + public LaunchSamlAuthenticationResponse setRelayState(String relayState) { + this.relayState = relayState; + return this; + } + + public String getSamlRequest() { + return samlRequest; + } + + public LaunchSamlAuthenticationResponse setSamlRequest(String samlRequest) { + this.samlRequest = samlRequest; + return this; + } + + public String getSigAlg() { + return sigAlg; + } + + public LaunchSamlAuthenticationResponse setSigAlg(String sigAlg) { + this.sigAlg = sigAlg; + return this; + } + + public String getSignature() { + return signature; + } + + public LaunchSamlAuthenticationResponse setSignature(String signature) { + this.signature = signature; + return this; + } } diff --git a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java index 9cd372c..1a9105d 100644 --- a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java +++ b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.oauth; diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index 2457f1e..04f4021 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.oauth; @@ -44,52 +45,52 @@ License, or (at your option) any later version. @Controller public class OAuthController { - private static final Logger LOG = LoggerFactory.getLogger(OAuthController.class); - - @Autowired - private RequestOrchestrationService validationService; - @Autowired - private TransparentAuthController transparentAuthController; - - @RequestMapping(value = "/oauth/authorize", method = RequestMethod.GET) - public String authorizeRequest( - @RequestParam(value = "response_type", required = false) String responseType, - @RequestParam(value = "client_id", required = false) String clientId, - @RequestParam(value = "redirect_uri", required = false) String redirectUri, - @RequestParam(value = "scope", required = false) String scopes, - @RequestParam(value = "state", required = false) String state, - @CookieValue(required = false) String identioSession, - HttpServletRequest httpRequest, - HttpServletResponse httpResponse) throws ValidationException, ServerException, WebSecurityException { - - LOG.info("Received OAuth authorization request from ClientId: {}", clientId); - LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); - - // Scopes are separated by a space - - List scopesList = new ArrayList<>(); - if (scopes != null) { - scopesList = Arrays.asList(scopes.split(" ")); - } - - OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesList, state); - - RequestValidationResult result = validationService.validateRequest(request, identioSession); - - switch (result.getValidationStatus()) { - case RESPONSE: - return "redirect:" + result.getResponseData().getUrl(); - - case CONSENT: - return "redirect:/#!/consent/"; - - case ERROR: - return "redirect:/#!/error/" + result.getErrorStatus(); - - default: - return transparentAuthController.checkTransparentAuthentication( - httpRequest, httpResponse, result.getSessionId(), result.getTransactionId()); - } - } + private static final Logger LOG = LoggerFactory.getLogger(OAuthController.class); + + @Autowired + private RequestOrchestrationService validationService; + @Autowired + private TransparentAuthController transparentAuthController; + + @RequestMapping(value = "/oauth/authorize", method = RequestMethod.GET) + public String authorizeRequest( + @RequestParam(value = "response_type", required = false) String responseType, + @RequestParam(value = "client_id", required = false) String clientId, + @RequestParam(value = "redirect_uri", required = false) String redirectUri, + @RequestParam(value = "scope", required = false) String scopes, + @RequestParam(value = "state", required = false) String state, + @CookieValue(required = false) String identioSession, + HttpServletRequest httpRequest, + HttpServletResponse httpResponse) throws ValidationException, ServerException, WebSecurityException { + + LOG.info("Received OAuth authorization request from ClientId: {}", clientId); + LOG.debug("RT: {} - RU: {} - SC: {} - ST: {}", responseType, redirectUri, scopes, state); + + // Scopes are separated by a space + + List scopesList = new ArrayList<>(); + if (scopes != null) { + scopesList = Arrays.asList(scopes.split(" ")); + } + + OAuthInboundRequest request = new OAuthInboundRequest(clientId, responseType, redirectUri, scopesList, state); + + RequestValidationResult result = validationService.validateRequest(request, identioSession); + + switch (result.getValidationStatus()) { + case RESPONSE: + return "redirect:" + result.getResponseData().getUrl(); + + case CONSENT: + return "redirect:/#!/consent/"; + + case ERROR: + return "redirect:/#!/error/" + result.getErrorStatus(); + + default: + return transparentAuthController.checkTransparentAuthentication( + httpRequest, httpResponse, result.getSessionId(), result.getTransactionId()); + } + } } diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java index 77461a2..db29b7a 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentContext.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.mvc.oauth.model; import net.identio.server.model.AuthorizationScope; diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java index af93830..564e7b5 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.mvc.oauth.model; import java.util.List; diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java index 5d46e44..fb889c7 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.mvc.oauth.model; public class ConsentResponse { diff --git a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java index b13254a..10ebebb 100644 --- a/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/AssertionConsumerController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.saml; @@ -44,49 +45,49 @@ License, or (at your option) any later version. @Controller public class AssertionConsumerController { - private static final Logger LOG = LoggerFactory.getLogger(AssertionConsumerController.class); + private static final Logger LOG = LoggerFactory.getLogger(AssertionConsumerController.class); - @Autowired - private AuthOrchestrationService authOrchestrationService; + @Autowired + private AuthOrchestrationService authOrchestrationService; - @Autowired - private ConfigurationService configurationService; + @Autowired + private ConfigurationService configurationService; - @Autowired - private ResponderController responderController; + @Autowired + private ResponderController responderController; - @RequestMapping(value = "/SAML2/ACS/POST", method = RequestMethod.POST) - public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, - @RequestParam("SAMLResponse") String usSamlResponse, - @RequestParam(value = "RelayState", required = false) String usRelayState, - @CookieValue String identioSession) throws ValidationException, ServerException, WebSecurityException { + @RequestMapping(value = "/SAML2/ACS/POST", method = RequestMethod.POST) + public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, + @RequestParam("SAMLResponse") String usSamlResponse, + @RequestParam(value = "RelayState", required = false) String usRelayState, + @CookieValue String identioSession) throws ValidationException, ServerException, WebSecurityException { - LOG.debug("Received SAML response on /SAML2/ACS/POST"); - LOG.debug("* SAMLResponse: {}", usSamlResponse); - LOG.debug("* RelayState: {}", usRelayState); + LOG.debug("Received SAML response on /SAML2/ACS/POST"); + LOG.debug("* SAMLResponse: {}", usSamlResponse); + LOG.debug("* RelayState: {}", usRelayState); - // To prevent XSS attacks, we escape the RelayState value - String transactionId = HtmlUtils.htmlEscape(usRelayState); - SamlAuthentication authentication = new SamlAuthentication(usSamlResponse); + // To prevent XSS attacks, we escape the RelayState value + String transactionId = HtmlUtils.htmlEscape(usRelayState); + SamlAuthentication authentication = new SamlAuthentication(usSamlResponse); - AuthenticationValidationResult result = authOrchestrationService - .handleExplicitAuthentication(transactionId, identioSession, null, authentication); + AuthenticationValidationResult result = authOrchestrationService + .handleExplicitAuthentication(transactionId, identioSession, null, authentication); - if (result.getValidationStatus() == ValidationStatus.RESPONSE) { + if (result.getValidationStatus() == ValidationStatus.RESPONSE) { - String responseView = responderController.displayResponderPage( - result.getResponseData().getUrl(), result.getResponseData().getData(), - result.getResponseData().getRelayState(), identioSession, httpResponse); - return responseView; + String responseView = responderController.displayResponderPage( + result.getResponseData().getUrl(), result.getResponseData().getData(), + result.getResponseData().getRelayState(), identioSession, httpResponse); + return responseView; - } else { - LOG.debug("Displaying authentication page"); + } else { + LOG.debug("Displaying authentication page"); - HttpUtils.setSessionCookie(httpResponse, identioSession, - configurationService.getConfiguration().getGlobalConfiguration().isSecure()); + HttpUtils.setSessionCookie(httpResponse, identioSession, + configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - return "redirect:/#!/auth/" + transactionId; - } + return "redirect:/#!/auth/" + transactionId; + } - } + } } diff --git a/src/main/java/net/identio/server/mvc/saml/MetadataController.java b/src/main/java/net/identio/server/mvc/saml/MetadataController.java index 8dfc462..6cfd80f 100644 --- a/src/main/java/net/identio/server/mvc/saml/MetadataController.java +++ b/src/main/java/net/identio/server/mvc/saml/MetadataController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.saml; @@ -35,33 +36,33 @@ License, or (at your option) any later version. @Controller public class MetadataController { - private static final Logger LOG = LoggerFactory.getLogger(MetadataController.class); + private static final Logger LOG = LoggerFactory.getLogger(MetadataController.class); - @Autowired - private MetadataService metadataService; + @Autowired + private MetadataService metadataService; - @RequestMapping(value = "/SAML2", method = RequestMethod.GET) - public void getIdpMetadata(HttpServletResponse httpResponse) throws ServerException { + @RequestMapping(value = "/SAML2", method = RequestMethod.GET) + public void getIdpMetadata(HttpServletResponse httpResponse) throws ServerException { - LOG.debug("Received IDP metadata request..."); + LOG.debug("Received IDP metadata request..."); - String returnValue = metadataService.getIdpMetadata().toString(); + String returnValue = metadataService.getIdpMetadata().toString(); - httpResponse.setContentType("application/samlmetadata+xml"); - httpResponse.setContentLength(returnValue.length()); - httpResponse.setHeader("Content-Disposition", "attachment; filename=\"identio-idp-metadata.xml\""); + httpResponse.setContentType("application/samlmetadata+xml"); + httpResponse.setContentLength(returnValue.length()); + httpResponse.setHeader("Content-Disposition", "attachment; filename=\"identio-idp-metadata.xml\""); - try (Writer writer = httpResponse.getWriter()) { - writer.write(returnValue); - writer.flush(); + try (Writer writer = httpResponse.getWriter()) { + writer.write(returnValue); + writer.flush(); - } catch (IOException ex) { - LOG.error("IOException when generating metadata"); - LOG.debug(" * Detailed Stacktrace:", ex); - throw new ServerException("IOException when generating metadata", ex); - } + } catch (IOException ex) { + LOG.error("IOException when generating metadata"); + LOG.debug(" * Detailed Stacktrace:", ex); + throw new ServerException("IOException when generating metadata", ex); + } - LOG.debug("IDP metadata successfully generated"); + LOG.debug("IDP metadata successfully generated"); - } + } } diff --git a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java index 080d1ab..6dd155e 100644 --- a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.saml; @@ -49,140 +50,139 @@ License, or (at your option) any later version. @Controller public class RequestConsumerController { - private static final Logger LOG = LoggerFactory.getLogger(RequestConsumerController.class); - - @Autowired - private RequestOrchestrationService validationService; - @Autowired - private TransparentAuthController transparentAuthController; - @Autowired - private ResponderController responderController; - - @RequestMapping(value = "/SAML2/SSO/POST", method = RequestMethod.POST) - public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, - @RequestParam("SAMLRequest") String usSamlRequest, - @RequestParam(value = "RelayState", required = false) String usRelayState, - @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { - - String decodedSamlRequest; - String decodedRelayState; - - LOG.debug("Received request on /SAML2/SSO/POST"); - LOG.debug("* SAMLRequest: {}", usSamlRequest); - LOG.debug("* RelayState: {}", usRelayState); - - // The SAML request is Base-64 encoded - try { - decodedSamlRequest = new String(DecodeUtils.decode(usSamlRequest, false)); - } catch (Base64DecodingException | IOException | DataFormatException e) { - throw new ServerException("Error when decoding SAML Request", e); - } - - // To prevent XSS attacks, we escape the RelayState value - decodedRelayState = HtmlUtils.htmlEscape(usRelayState); - - return processRequest(httpRequest, httpResponse, SamlConstants.BINDING_HTTP_POST, decodedSamlRequest, - decodedRelayState, null, null, null, identioSession); - - } - - /** - * Receives a request through HTTP redirect binding - * - * @throws ServerException - * @throws NoAuthMethodFoundException - * @throws UnknownAuthLevelException - * @throws SamlException - * @throws ValidationException - * - */ - @RequestMapping(value = "/SAML2/SSO/Redirect", method = RequestMethod.GET) - public String samlConsumerRedirect(HttpServletRequest httpRequest, HttpServletResponse httpResponse, - @RequestParam("SAMLRequest") String usSamlRequest, - @RequestParam(value = "RelayState", required = false) String usRelayState, - @RequestParam(value = "SigAlg", required = false) String usSigAlg, - @RequestParam(value = "Signature", required = false) String usSignature, - @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { - - String signedInfo = null; - String decodedSamlRequest = null; - String decodedRelayState = null; - - LOG.debug("Received request on /SAML2/SSO/Redirect"); - LOG.debug("* SAMLRequest: {}", usSamlRequest); - LOG.debug("* RelayState: {}", usRelayState); - LOG.debug("* SigAlg: {}", usSigAlg); - LOG.debug("* Signature: {}", usSignature); - - if (usSignature != null) { - - // The signature is based on the URL-encoded values. As Spring does - // the conversion automatically, we have to extract the values from - // the query string - String[] queryString = httpRequest.getQueryString().split("&"); - - String encodedSamlRequest = null; - String encodedRelayState = null; - String encodedSigAlg = null; - - for (String element : queryString) { - - LOG.debug("Query string parameter: {}", element); - - if (element.startsWith("SAMLRequest")) - encodedSamlRequest = element; - if (element.startsWith("RelayState")) - encodedRelayState = element; - if (element.startsWith("SigAlg")) - encodedSigAlg = element; - } - - if (encodedRelayState != null) { - signedInfo = encodedSamlRequest + "&" + encodedRelayState + "&" + encodedSigAlg; - } else { - signedInfo = encodedSamlRequest + "&" + encodedSigAlg; - } - - LOG.debug("Signed Info: {}", signedInfo); - } - - // The SAML request is Base-64 encoded and deflated - try { - decodedSamlRequest = new String(DecodeUtils.decode(usSamlRequest, true)); - } catch (IOException | Base64DecodingException | DataFormatException e) { - throw new ServerException("Error when decoding SAML Request", e); - } - - // To prevent XSS attacks, we escape the RelayState value - decodedRelayState = HtmlUtils.htmlEscape(usRelayState); - - return processRequest(httpRequest, httpResponse, SamlConstants.BINDING_HTTP_REDIRECT, decodedSamlRequest, - decodedRelayState, usSigAlg, usSignature, signedInfo, identioSession); - - } - - private String processRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String binding, - String request, String relayState, String sigAlg, String signatureValue, String signedInfo, - String sessionId) throws ServerException, ValidationException, WebSecurityException { - - LOG.debug("Processing SAML authentication request."); - - SamlInboundRequest samlRequest = new SamlInboundRequest(binding, request, signatureValue, signedInfo, sigAlg, - relayState); - - // The request is forwarded to the orchestration service - RequestValidationResult result = validationService.validateRequest(samlRequest, sessionId); - - if (result.getValidationStatus() == ValidationStatus.RESPONSE) { - - return responderController.displayResponderPage( - result.getResponseData().getUrl(), result.getResponseData().getData(), - result.getResponseData().getRelayState(), result.getSessionId(), httpResponse); - - } else { - return transparentAuthController.checkTransparentAuthentication(httpRequest, httpResponse, - result.getSessionId(), result.getTransactionId()); - } - - } + private static final Logger LOG = LoggerFactory.getLogger(RequestConsumerController.class); + + @Autowired + private RequestOrchestrationService validationService; + @Autowired + private TransparentAuthController transparentAuthController; + @Autowired + private ResponderController responderController; + + @RequestMapping(value = "/SAML2/SSO/POST", method = RequestMethod.POST) + public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletResponse httpResponse, + @RequestParam("SAMLRequest") String usSamlRequest, + @RequestParam(value = "RelayState", required = false) String usRelayState, + @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { + + String decodedSamlRequest; + String decodedRelayState; + + LOG.debug("Received request on /SAML2/SSO/POST"); + LOG.debug("* SAMLRequest: {}", usSamlRequest); + LOG.debug("* RelayState: {}", usRelayState); + + // The SAML request is Base-64 encoded + try { + decodedSamlRequest = new String(DecodeUtils.decode(usSamlRequest, false)); + } catch (Base64DecodingException | IOException | DataFormatException e) { + throw new ServerException("Error when decoding SAML Request", e); + } + + // To prevent XSS attacks, we escape the RelayState value + decodedRelayState = HtmlUtils.htmlEscape(usRelayState); + + return processRequest(httpRequest, httpResponse, SamlConstants.BINDING_HTTP_POST, decodedSamlRequest, + decodedRelayState, null, null, null, identioSession); + + } + + /** + * Receives a request through HTTP redirect binding + * + * @throws ServerException + * @throws NoAuthMethodFoundException + * @throws UnknownAuthLevelException + * @throws SamlException + * @throws ValidationException + */ + @RequestMapping(value = "/SAML2/SSO/Redirect", method = RequestMethod.GET) + public String samlConsumerRedirect(HttpServletRequest httpRequest, HttpServletResponse httpResponse, + @RequestParam("SAMLRequest") String usSamlRequest, + @RequestParam(value = "RelayState", required = false) String usRelayState, + @RequestParam(value = "SigAlg", required = false) String usSigAlg, + @RequestParam(value = "Signature", required = false) String usSignature, + @CookieValue(required = false) String identioSession) throws ServerException, ValidationException, WebSecurityException { + + String signedInfo = null; + String decodedSamlRequest = null; + String decodedRelayState = null; + + LOG.debug("Received request on /SAML2/SSO/Redirect"); + LOG.debug("* SAMLRequest: {}", usSamlRequest); + LOG.debug("* RelayState: {}", usRelayState); + LOG.debug("* SigAlg: {}", usSigAlg); + LOG.debug("* Signature: {}", usSignature); + + if (usSignature != null) { + + // The signature is based on the URL-encoded values. As Spring does + // the conversion automatically, we have to extract the values from + // the query string + String[] queryString = httpRequest.getQueryString().split("&"); + + String encodedSamlRequest = null; + String encodedRelayState = null; + String encodedSigAlg = null; + + for (String element : queryString) { + + LOG.debug("Query string parameter: {}", element); + + if (element.startsWith("SAMLRequest")) + encodedSamlRequest = element; + if (element.startsWith("RelayState")) + encodedRelayState = element; + if (element.startsWith("SigAlg")) + encodedSigAlg = element; + } + + if (encodedRelayState != null) { + signedInfo = encodedSamlRequest + "&" + encodedRelayState + "&" + encodedSigAlg; + } else { + signedInfo = encodedSamlRequest + "&" + encodedSigAlg; + } + + LOG.debug("Signed Info: {}", signedInfo); + } + + // The SAML request is Base-64 encoded and deflated + try { + decodedSamlRequest = new String(DecodeUtils.decode(usSamlRequest, true)); + } catch (IOException | Base64DecodingException | DataFormatException e) { + throw new ServerException("Error when decoding SAML Request", e); + } + + // To prevent XSS attacks, we escape the RelayState value + decodedRelayState = HtmlUtils.htmlEscape(usRelayState); + + return processRequest(httpRequest, httpResponse, SamlConstants.BINDING_HTTP_REDIRECT, decodedSamlRequest, + decodedRelayState, usSigAlg, usSignature, signedInfo, identioSession); + + } + + private String processRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse, String binding, + String request, String relayState, String sigAlg, String signatureValue, String signedInfo, + String sessionId) throws ServerException, ValidationException, WebSecurityException { + + LOG.debug("Processing SAML authentication request."); + + SamlInboundRequest samlRequest = new SamlInboundRequest(binding, request, signatureValue, signedInfo, sigAlg, + relayState); + + // The request is forwarded to the orchestration service + RequestValidationResult result = validationService.validateRequest(samlRequest, sessionId); + + if (result.getValidationStatus() == ValidationStatus.RESPONSE) { + + return responderController.displayResponderPage( + result.getResponseData().getUrl(), result.getResponseData().getData(), + result.getResponseData().getRelayState(), result.getSessionId(), httpResponse); + + } else { + return transparentAuthController.checkTransparentAuthentication(httpRequest, httpResponse, + result.getSessionId(), result.getTransactionId()); + } + + } } diff --git a/src/main/java/net/identio/server/mvc/saml/ResponderController.java b/src/main/java/net/identio/server/mvc/saml/ResponderController.java index 21874c0..8c811fd 100644 --- a/src/main/java/net/identio/server/mvc/saml/ResponderController.java +++ b/src/main/java/net/identio/server/mvc/saml/ResponderController.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.mvc.saml; @@ -34,36 +35,36 @@ License, or (at your option) any later version. @Controller public class ResponderController { - private static final Logger LOG = LoggerFactory.getLogger(ResponderController.class); + private static final Logger LOG = LoggerFactory.getLogger(ResponderController.class); - @Autowired - private ConfigurationService configurationService; + @Autowired + private ConfigurationService configurationService; - public String displayResponderPage(String destinationUrl, String responseData, String relayState, String sessionId, - HttpServletResponse httpResponse) throws ServerException { + public String displayResponderPage(String destinationUrl, String responseData, String relayState, String sessionId, + HttpServletResponse httpResponse) throws ServerException { - LOG.info("Generation of a SAML Response"); + LOG.info("Generation of a SAML Response"); - HttpUtils.setSessionCookie(httpResponse, sessionId, - configurationService.getConfiguration().getGlobalConfiguration().isSecure()); + HttpUtils.setSessionCookie(httpResponse, sessionId, + configurationService.getConfiguration().getGlobalConfiguration().isSecure()); - String responseForm = "Ident.io SAML Responder
"; + String responseForm = "Ident.io SAML Responder
"; - httpResponse.setContentType("text/html"); + httpResponse.setContentType("text/html"); - try (Writer writer = httpResponse.getWriter()) { - writer.write(responseForm); - writer.flush(); + try (Writer writer = httpResponse.getWriter()) { + writer.write(responseForm); + writer.flush(); - } catch (IOException ex) { - LOG.error("IOException when generating response form"); - LOG.debug(" * Detailed Stacktrace:", ex); - throw new ServerException("IOException when generating response form", ex); - } + } catch (IOException ex) { + LOG.error("IOException when generating response form"); + LOG.debug(" * Detailed Stacktrace:", ex); + throw new ServerException("IOException when generating response form", ex); + } - return null; - } + return null; + } } diff --git a/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java index b4eb2dd..c994548 100644 --- a/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/AuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication; @@ -26,8 +27,8 @@ License, or (at your option) any later version. public interface AuthenticationProvider { - boolean accepts(Authentication authentication); + boolean accepts(Authentication authentication); - AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData); + AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData); } diff --git a/src/main/java/net/identio/server/service/authentication/AuthenticationService.java b/src/main/java/net/identio/server/service/authentication/AuthenticationService.java index 4d6b66b..5d3040e 100644 --- a/src/main/java/net/identio/server/service/authentication/AuthenticationService.java +++ b/src/main/java/net/identio/server/service/authentication/AuthenticationService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication; @@ -33,69 +34,69 @@ License, or (at your option) any later version. @Service public class AuthenticationService { - private static final Logger LOG = LoggerFactory.getLogger(AuthenticationService.class); + private static final Logger LOG = LoggerFactory.getLogger(AuthenticationService.class); + + private HashMap explicitAuthenticationProviders = new HashMap<>(); + private HashMap transparentAuthenticationProviders = new HashMap<>(); - private HashMap explicitAuthenticationProviders = new HashMap<>(); - private HashMap transparentAuthenticationProviders = new HashMap<>(); + public void registerExplicit(AuthMethod authMethod, AuthenticationProvider provider) throws IllegalArgumentException { - public void registerExplicit(AuthMethod authMethod, AuthenticationProvider provider) throws IllegalArgumentException { + LOG.info("Registering explicit method {}", authMethod.getName()); - LOG.info("Registering explicit method {}", authMethod.getName()); + if (explicitAuthenticationProviders.containsKey(authMethod)) { + String message = "Authentication method name already in use"; + LOG.error(message); + throw new IllegalArgumentException(message); + } - if (explicitAuthenticationProviders.containsKey(authMethod)) { - String message = "Authentication method name already in use"; - LOG.error(message); - throw new IllegalArgumentException(message); - } + explicitAuthenticationProviders.put(authMethod, provider); + } - explicitAuthenticationProviders.put(authMethod, provider); - } + public void registerTransparent(AuthMethod authMethod, AuthenticationProvider provider) throws IllegalArgumentException { - public void registerTransparent(AuthMethod authMethod, AuthenticationProvider provider) throws IllegalArgumentException { + LOG.info("Registering transparent method {}", authMethod.getName()); - LOG.info("Registering transparent method {}", authMethod.getName()); - - if (transparentAuthenticationProviders.containsKey(authMethod.getName())) { - String message = "Authentication method name already in use"; - LOG.error(message); - throw new IllegalArgumentException(message); - } + if (transparentAuthenticationProviders.containsKey(authMethod.getName())) { + String message = "Authentication method name already in use"; + LOG.error(message); + throw new IllegalArgumentException(message); + } - transparentAuthenticationProviders.put(authMethod, provider); - } + transparentAuthenticationProviders.put(authMethod, provider); + } - public AuthenticationResult validateTransparent(Authentication authentication, TransactionData transactionData) { + public AuthenticationResult validateTransparent(Authentication authentication, TransactionData transactionData) { - AuthenticationResult result = null; + AuthenticationResult result = null; - for (AuthMethod authMethod : transparentAuthenticationProviders.keySet()) { + for (AuthMethod authMethod : transparentAuthenticationProviders.keySet()) { - AuthenticationProvider provider = transparentAuthenticationProviders.get(authMethod); + AuthenticationProvider provider = transparentAuthenticationProviders.get(authMethod); - if (provider.accepts(authentication)) { - result = provider.validate(authMethod, authentication, transactionData); + if (provider.accepts(authentication)) { + result = provider.validate(authMethod, authentication, transactionData); - if (result.getStatus() != AuthenticationResultStatus.FAIL) { - break; - } + if (result.getStatus() != AuthenticationResultStatus.FAIL) { + break; + } - } - } + } + } - return result; - } + return result; + } - public AuthenticationResult validateExplicit(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + public AuthenticationResult validateExplicit(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData) { - AuthenticationResult result = null; + AuthenticationResult result = null; - AuthenticationProvider provider = explicitAuthenticationProviders.get(authMethod); + AuthenticationProvider provider = explicitAuthenticationProviders.get(authMethod); - if (provider.accepts(authentication)) { - result = provider.validate(authMethod, authentication, transactionData); - } + if (provider.accepts(authentication)) { + result = provider.validate(authMethod, authentication, transactionData); + } - return result; - } + return result; + } } diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java index ccedff0..3cb600c 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapAuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.ldap; @@ -51,178 +52,178 @@ License, or (at your option) any later version. @Scope("singleton") public class LdapAuthenticationProvider implements AuthenticationProvider { - private static final Logger LOG = LoggerFactory.getLogger(LdapAuthenticationProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(LdapAuthenticationProvider.class); - private HashMap> pools = new HashMap>(); + private HashMap> pools = new HashMap>(); - private HashMap ldapAuthMethodsMap = new HashMap(); + private HashMap ldapAuthMethodsMap = new HashMap(); - @Autowired - public LdapAuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) throws InitializationException { + @Autowired + public LdapAuthenticationProvider(ConfigurationService configurationService, + AuthenticationService authenticationService) throws InitializationException { - List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() - .getLdapAuthMethods(); + List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() + .getLdapAuthMethods(); - if (authMethods == null) - return; + if (authMethods == null) + return; - LOG.debug("Initializing LDAP Authentication Service"); + LOG.debug("Initializing LDAP Authentication Service"); - initTrustore(authMethods); + initTrustore(authMethods); - initPool(authMethods); + initPool(authMethods); - register(authMethods, authenticationService); + register(authMethods, authenticationService); - LOG.info("* LDAP Authentication Service initialized"); + LOG.info("* LDAP Authentication Service initialized"); - } + } - public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData) { - LdapAuthMethod ldapAuthMethod = (LdapAuthMethod) authMethod; - UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; + LdapAuthMethod ldapAuthMethod = (LdapAuthMethod) authMethod; + UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; - boolean validation; + boolean validation; - String userId = userPwAuthentication.getUserId(); - String password = userPwAuthentication.getPassword(); + String userId = userPwAuthentication.getUserId(); + String password = userPwAuthentication.getPassword(); - GenericObjectPool pool = pools.get(authMethod.getName()); + GenericObjectPool pool = pools.get(authMethod.getName()); - InitialLdapContext ctx = null; + InitialLdapContext ctx = null; - try { - ctx = pool.borrowObject(); + try { + ctx = pool.borrowObject(); - // First we search the user - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + // First we search the user + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchFilter = ldapAuthMethod.getUserSearchFilter().replace("#UID", - SecurityUtils.escapeLDAPSearchFilter(userId)); + String searchFilter = ldapAuthMethod.getUserSearchFilter().replace("#UID", + SecurityUtils.escapeLDAPSearchFilter(userId)); - NamingEnumeration results = ctx.search(ldapAuthMethod.getBaseDn(), searchFilter, controls); + NamingEnumeration results = ctx.search(ldapAuthMethod.getBaseDn(), searchFilter, controls); - SearchResult result; + SearchResult result; - if (results.hasMoreElements()) { - result = results.next(); + if (results.hasMoreElements()) { + result = results.next(); - if (results.hasMoreElements()) { - LOG.error("User ID {} is not unique in LDAP {}", userId, authMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.USER_NOT_UNIQUE); - } - } else { - LOG.error("User ID {} does not exist in LDAP {}", userId, authMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + if (results.hasMoreElements()) { + LOG.error("User ID {} is not unique in LDAP {}", userId, authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.USER_NOT_UNIQUE); + } + } else { + LOG.error("User ID {} does not exist in LDAP {}", userId, authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - // Try to bind with the found user id - validation = ((LdapConnectionFactory) pool.getFactory()).authenticate(authMethod.getName(), - result.getNameInNamespace(), password); + // Try to bind with the found user id + validation = ((LdapConnectionFactory) pool.getFactory()).authenticate(authMethod.getName(), + result.getNameInNamespace(), password); - pool.returnObject(ctx); + pool.returnObject(ctx); - if (validation) { - LOG.info("User {} successfully authenticated with {}", userId, authMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) - .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); - } else { - LOG.error("Authentication failed for user {} with {}", userId, authMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + if (validation) { + LOG.info("User {} successfully authenticated with {}", userId, authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) + .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); + } else { + LOG.error("Authentication failed for user {} with {}", userId, authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - } catch (Exception ex) { + } catch (Exception ex) { - // Discard context - try { - if (ctx != null) { - pool.invalidateObject(ctx); - } - } catch (Exception ex2) { - LOG.error("An error occurend when authenticating user"); - } + // Discard context + try { + if (ctx != null) { + pool.invalidateObject(ctx); + } + } catch (Exception ex2) { + LOG.error("An error occurend when authenticating user"); + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); - } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); + } - } + } - private void initPool(List ldapAuthMethods) { + private void initPool(List ldapAuthMethods) { - for (LdapAuthMethod ldapAuthMethod : ldapAuthMethods) { + for (LdapAuthMethod ldapAuthMethod : ldapAuthMethods) { - LOG.debug("* Auth Method: {}", ldapAuthMethod.getName()); + LOG.debug("* Auth Method: {}", ldapAuthMethod.getName()); - ldapAuthMethodsMap.put(ldapAuthMethod.getName(), ldapAuthMethod); + ldapAuthMethodsMap.put(ldapAuthMethod.getName(), ldapAuthMethod); - LdapConnectionFactory factory = new LdapConnectionFactory(ldapAuthMethod); + LdapConnectionFactory factory = new LdapConnectionFactory(ldapAuthMethod); - GenericObjectPool pool = new GenericObjectPool<>(factory); + GenericObjectPool pool = new GenericObjectPool<>(factory); - LdapPoolConfig poolConfig = ldapAuthMethod.getPoolConfig(); + LdapPoolConfig poolConfig = ldapAuthMethod.getPoolConfig(); - pool.setMinIdle(poolConfig.getMinIdleConnections()); - pool.setMaxIdle(poolConfig.getMaxIdleConnections()); - pool.setBlockWhenExhausted(true); - pool.setTestWhileIdle(poolConfig.isTestWhileIdle()); - pool.setTestOnBorrow(poolConfig.isTestOnBorrow()); - pool.setTimeBetweenEvictionRunsMillis(1000 * poolConfig.getTimeBetweenEvictionRuns()); - pool.setNumTestsPerEvictionRun(poolConfig.getNumTestsPerEvictionRun()); - pool.setMinEvictableIdleTimeMillis(1000 * poolConfig.getMinEvictableIdleTime()); + pool.setMinIdle(poolConfig.getMinIdleConnections()); + pool.setMaxIdle(poolConfig.getMaxIdleConnections()); + pool.setBlockWhenExhausted(true); + pool.setTestWhileIdle(poolConfig.isTestWhileIdle()); + pool.setTestOnBorrow(poolConfig.isTestOnBorrow()); + pool.setTimeBetweenEvictionRunsMillis(1000 * poolConfig.getTimeBetweenEvictionRuns()); + pool.setNumTestsPerEvictionRun(poolConfig.getNumTestsPerEvictionRun()); + pool.setMinEvictableIdleTimeMillis(1000 * poolConfig.getMinEvictableIdleTime()); - pools.put(ldapAuthMethod.getName(), pool); + pools.put(ldapAuthMethod.getName(), pool); - } - } + } + } - private void initTrustore(List ldapAuthMethods) throws InitializationException { + private void initTrustore(List ldapAuthMethods) throws InitializationException { - LOG.debug("* Init trust store for SSL connections"); + LOG.debug("* Init trust store for SSL connections"); - // Init keystore - try { + // Init keystore + try { - KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(null, null); + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, null); - // Add each trust certificate to the keystore - for (LdapAuthMethod ldapAuthMethod : ldapAuthMethods) { + // Add each trust certificate to the keystore + for (LdapAuthMethod ldapAuthMethod : ldapAuthMethods) { - if (ldapAuthMethod.getTrustCert() != null) { + if (ldapAuthMethod.getTrustCert() != null) { - SecurityUtils.addCertificateToKeyStore(ks, - SecurityUtils.parseCertificate(ldapAuthMethod.getTrustCert()), ldapAuthMethod.getName()); - } - } + SecurityUtils.addCertificateToKeyStore(ks, + SecurityUtils.parseCertificate(ldapAuthMethod.getTrustCert()), ldapAuthMethod.getName()); + } + } - LdapSslSocketFactory.init(ks); + LdapSslSocketFactory.init(ks); - } catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException | CertificateException - | IOException ex) { - throw new InitializationException("Error when initializing keystore with trusted certificates", ex); - } - } + } catch (KeyManagementException | KeyStoreException | NoSuchAlgorithmException | CertificateException + | IOException ex) { + throw new InitializationException("Error when initializing keystore with trusted certificates", ex); + } + } - private void register(List authMethods, AuthenticationService authenticationService) { + private void register(List authMethods, AuthenticationService authenticationService) { - for (LdapAuthMethod authMethod : authMethods) { + for (LdapAuthMethod authMethod : authMethods) { - LOG.debug("* Registering authentication method {}", authMethod.getName()); + LOG.debug("* Registering authentication method {}", authMethod.getName()); - authenticationService.registerExplicit(authMethod, this); - } - } + authenticationService.registerExplicit(authMethod, this); + } + } - @Override - public boolean accepts(Authentication authentication) { - return authentication instanceof UserPasswordAuthentication; - } + @Override + public boolean accepts(Authentication authentication) { + return authentication instanceof UserPasswordAuthentication; + } } diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java index 0a76ecf..f38e29d 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapConnectionFactory.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.ldap; @@ -35,142 +36,142 @@ License, or (at your option) any later version. public class LdapConnectionFactory extends BasePooledObjectFactory { - private static final Logger LOG = LoggerFactory.getLogger(LdapConnectionFactory.class); + private static final Logger LOG = LoggerFactory.getLogger(LdapConnectionFactory.class); - private LdapAuthMethod ldapAuthMethod; + private LdapAuthMethod ldapAuthMethod; - private int currentUrlIndex; + private int currentUrlIndex; - public LdapConnectionFactory(LdapAuthMethod ldapAuthMethod) { - this.ldapAuthMethod = ldapAuthMethod; + public LdapConnectionFactory(LdapAuthMethod ldapAuthMethod) { + this.ldapAuthMethod = ldapAuthMethod; - currentUrlIndex = 0; - } + currentUrlIndex = 0; + } - @Override - public InitialLdapContext create() throws NamingException { + @Override + public InitialLdapContext create() throws NamingException { - InitialLdapContext ctx = createContext(ldapAuthMethod, ldapAuthMethod.getProxyUser(), - ldapAuthMethod.getProxyPassword()); + InitialLdapContext ctx = createContext(ldapAuthMethod, ldapAuthMethod.getProxyUser(), + ldapAuthMethod.getProxyPassword()); - LOG.debug("Created LDAP connection to: {}", ldapAuthMethod.getName()); + LOG.debug("Created LDAP connection to: {}", ldapAuthMethod.getName()); - return ctx; - } + return ctx; + } - public boolean authenticate(String name, String dn, String password) { + public boolean authenticate(String name, String dn, String password) { - InitialLdapContext ctx = null; + InitialLdapContext ctx = null; - try { - ctx = createContext(ldapAuthMethod, dn, password); + try { + ctx = createContext(ldapAuthMethod, dn, password); - return true; - } catch (NamingException e) { + return true; + } catch (NamingException e) { - return false; - } finally { - if (ctx != null) { - try { - ctx.close(); - } catch (NamingException e) { - LOG.error("Error when closing connection to LDAP {}", ldapAuthMethod.getName()); - } - } - } - } + return false; + } finally { + if (ctx != null) { + try { + ctx.close(); + } catch (NamingException e) { + LOG.error("Error when closing connection to LDAP {}", ldapAuthMethod.getName()); + } + } + } + } - private InitialLdapContext createContext(LdapAuthMethod ldapAuthMethod, String userDn, String password) - throws NamingException { + private InitialLdapContext createContext(LdapAuthMethod ldapAuthMethod, String userDn, String password) + throws NamingException { - LOG.debug("Begin creation of an LDAP connection to: {}", ldapAuthMethod.getName()); + LOG.debug("Begin creation of an LDAP connection to: {}", ldapAuthMethod.getName()); - int currentUrlIndexTs = currentUrlIndex; + int currentUrlIndexTs = currentUrlIndex; - String currentUrl = ldapAuthMethod.getLdapUrl()[currentUrlIndexTs]; + String currentUrl = ldapAuthMethod.getLdapUrl()[currentUrlIndexTs]; - Hashtable env = new Hashtable(); - env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.put(Context.PROVIDER_URL, currentUrl); + Hashtable env = new Hashtable(); + env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + env.put(Context.PROVIDER_URL, currentUrl); - if (currentUrl.startsWith("ldaps://")) { + if (currentUrl.startsWith("ldaps://")) { - // Add a custom SSL Socket factory to validate server CA - env.put("java.naming.ldap.factory.socket", - "net.identio.server.service.authentication.ldap.LdapSslSocketFactory"); - } + // Add a custom SSL Socket factory to validate server CA + env.put("java.naming.ldap.factory.socket", + "net.identio.server.service.authentication.ldap.LdapSslSocketFactory"); + } - if (userDn != null) { - env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, userDn); - env.put(Context.SECURITY_CREDENTIALS, password); - } + if (userDn != null) { + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + env.put(Context.SECURITY_PRINCIPAL, userDn); + env.put(Context.SECURITY_CREDENTIALS, password); + } - InitialLdapContext ctx = null; + InitialLdapContext ctx = null; - try { - ctx = new InitialLdapContext(env, null); - } catch (CommunicationException e) { + try { + ctx = new InitialLdapContext(env, null); + } catch (CommunicationException e) { - LOG.error("Error when contacting LDAP server {}", ldapAuthMethod.getLdapUrl()[currentUrlIndexTs]); + LOG.error("Error when contacting LDAP server {}", ldapAuthMethod.getLdapUrl()[currentUrlIndexTs]); - if (ldapAuthMethod.getLdapUrl().length > 1) { - int newCurrentUrlIndex = currentUrlIndexTs < ldapAuthMethod.getLdapUrl().length - 1 - ? currentUrlIndexTs + 1 : 0; + if (ldapAuthMethod.getLdapUrl().length > 1) { + int newCurrentUrlIndex = currentUrlIndexTs < ldapAuthMethod.getLdapUrl().length - 1 + ? currentUrlIndexTs + 1 : 0; - LOG.error("Switching to LDAP server {}", ldapAuthMethod.getLdapUrl()[newCurrentUrlIndex]); + LOG.error("Switching to LDAP server {}", ldapAuthMethod.getLdapUrl()[newCurrentUrlIndex]); - currentUrlIndex = newCurrentUrlIndex; + currentUrlIndex = newCurrentUrlIndex; - env.put(Context.PROVIDER_URL, ldapAuthMethod.getLdapUrl()[newCurrentUrlIndex]); + env.put(Context.PROVIDER_URL, ldapAuthMethod.getLdapUrl()[newCurrentUrlIndex]); - ctx = new InitialLdapContext(env, null); - } else { - throw e; - } - } + ctx = new InitialLdapContext(env, null); + } else { + throw e; + } + } - return ctx; - } + return ctx; + } - @Override - public PooledObject wrap(InitialLdapContext ctx) { - return new DefaultPooledObject(ctx); - } + @Override + public PooledObject wrap(InitialLdapContext ctx) { + return new DefaultPooledObject(ctx); + } - @Override - public void destroyObject(PooledObject p) { + @Override + public void destroyObject(PooledObject p) { - LOG.debug("Begin destruction of an LDAP connection to: {}", ldapAuthMethod.getName()); + LOG.debug("Begin destruction of an LDAP connection to: {}", ldapAuthMethod.getName()); - try { - p.getObject().close(); + try { + p.getObject().close(); - LOG.debug("Destroyed LDAP connection to: {}", ldapAuthMethod.getName()); + LOG.debug("Destroyed LDAP connection to: {}", ldapAuthMethod.getName()); - } catch (NamingException e) { - LOG.error("Error when closing connection to LDAP server {}", ldapAuthMethod.getName()); - } - } + } catch (NamingException e) { + LOG.error("Error when closing connection to LDAP server {}", ldapAuthMethod.getName()); + } + } - @Override - public boolean validateObject(PooledObject p) { + @Override + public boolean validateObject(PooledObject p) { - LOG.debug("Validating connection to LDAP directory {}", ldapAuthMethod.getName()); + LOG.debug("Validating connection to LDAP directory {}", ldapAuthMethod.getName()); - SearchControls controls = new SearchControls(); - controls.setSearchScope(SearchControls.SUBTREE_SCOPE); - controls.setCountLimit(1); - controls.setTimeLimit(500); + SearchControls controls = new SearchControls(); + controls.setSearchScope(SearchControls.SUBTREE_SCOPE); + controls.setCountLimit(1); + controls.setTimeLimit(500); - try { - p.getObject().search("", ldapAuthMethod.getPoolConfig().getTestRequestFilter(), controls); - } catch (NamingException e) { - LOG.error("Validation of connection to LDAP directory {} failed", ldapAuthMethod.getName()); - return false; - } + try { + p.getObject().search("", ldapAuthMethod.getPoolConfig().getTestRequestFilter(), controls); + } catch (NamingException e) { + LOG.error("Validation of connection to LDAP directory {} failed", ldapAuthMethod.getName()); + return false; + } - return true; - } + return true; + } } diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java index a2e5e0f..cfd4e5b 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.ldap; @@ -31,61 +32,61 @@ License, or (at your option) any later version. public class LdapSslSocketFactory extends SSLSocketFactory { - private static SSLContext context; - - public static synchronized void init(KeyStore keyStore) - throws KeyManagementException, NoSuchAlgorithmException, - KeyStoreException { - - TrustManagerFactory trustManagerFactory = TrustManagerFactory - .getInstance("X509"); - trustManagerFactory.init(keyStore); - context = SSLContext.getInstance("TLS"); - context.init(null, trustManagerFactory.getTrustManagers(), - SecureRandom.getInstance("SHA1PRNG")); - } - - public static SocketFactory getDefault() { - return new LdapSslSocketFactory(); - } - - @Override - public String[] getDefaultCipherSuites() { - return context.getSocketFactory().getDefaultCipherSuites(); - } - - @Override - public String[] getSupportedCipherSuites() { - return context.getSocketFactory().getSupportedCipherSuites(); - } - - @Override - public Socket createSocket(Socket socket, String s, int i, boolean b) - throws IOException { - return context.getSocketFactory().createSocket(socket, s, i, b); - } - - @Override - public Socket createSocket(String s, int i) throws IOException { - return context.getSocketFactory().createSocket(s, i); - } - - @Override - public Socket createSocket(String s, int i, InetAddress inetAddress, int i2) - throws IOException { - return context.getSocketFactory().createSocket(s, i, inetAddress, i2); - } - - @Override - public Socket createSocket(InetAddress inetAddress, int i) - throws IOException { - return context.getSocketFactory().createSocket(inetAddress, i); - } - - @Override - public Socket createSocket(InetAddress inetAddress, int i, - InetAddress inetAddress2, int i2) throws IOException { - return context.getSocketFactory().createSocket(inetAddress, i, - inetAddress2, i2); - } + private static SSLContext context; + + public static synchronized void init(KeyStore keyStore) + throws KeyManagementException, NoSuchAlgorithmException, + KeyStoreException { + + TrustManagerFactory trustManagerFactory = TrustManagerFactory + .getInstance("X509"); + trustManagerFactory.init(keyStore); + context = SSLContext.getInstance("TLS"); + context.init(null, trustManagerFactory.getTrustManagers(), + SecureRandom.getInstance("SHA1PRNG")); + } + + public static SocketFactory getDefault() { + return new LdapSslSocketFactory(); + } + + @Override + public String[] getDefaultCipherSuites() { + return context.getSocketFactory().getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return context.getSocketFactory().getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(Socket socket, String s, int i, boolean b) + throws IOException { + return context.getSocketFactory().createSocket(socket, s, i, b); + } + + @Override + public Socket createSocket(String s, int i) throws IOException { + return context.getSocketFactory().createSocket(s, i); + } + + @Override + public Socket createSocket(String s, int i, InetAddress inetAddress, int i2) + throws IOException { + return context.getSocketFactory().createSocket(s, i, inetAddress, i2); + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i) + throws IOException { + return context.getSocketFactory().createSocket(inetAddress, i); + } + + @Override + public Socket createSocket(InetAddress inetAddress, int i, + InetAddress inetAddress2, int i2) throws IOException { + return context.getSocketFactory().createSocket(inetAddress, i, + inetAddress2, i2); + } } diff --git a/src/main/java/net/identio/server/service/authentication/local/FileUserRepository.java b/src/main/java/net/identio/server/service/authentication/local/FileUserRepository.java index 0101869..a871080 100644 --- a/src/main/java/net/identio/server/service/authentication/local/FileUserRepository.java +++ b/src/main/java/net/identio/server/service/authentication/local/FileUserRepository.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.local; @@ -23,14 +24,14 @@ License, or (at your option) any later version. public class FileUserRepository { - private List users; + private List users; - public List getUsers() { - return users; - } + public List getUsers() { + return users; + } - public void setUsers(List users) { - this.users = users; - } + public void setUsers(List users) { + this.users = users; + } } diff --git a/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java index 382fdf5..9798803 100644 --- a/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/local/LocalAuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.local; @@ -45,115 +46,115 @@ License, or (at your option) any later version. @Scope("singleton") public class LocalAuthenticationProvider implements AuthenticationProvider { - private static final Logger LOG = LoggerFactory.getLogger(LocalAuthenticationProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(LocalAuthenticationProvider.class); - private HashMap fileAuthMethodsMap = new HashMap(); + private HashMap fileAuthMethodsMap = new HashMap(); - private HashMap> globalUsersMap; + private HashMap> globalUsersMap; - @Autowired - public LocalAuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) throws InitializationException { + @Autowired + public LocalAuthenticationProvider(ConfigurationService configurationService, + AuthenticationService authenticationService) throws InitializationException { - List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() - .getLocalAuthMethods(); + List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() + .getLocalAuthMethods(); - if (authMethods == null) - return; + if (authMethods == null) + return; - LOG.info("Initializing File Authentication Service"); + LOG.info("Initializing File Authentication Service"); - globalUsersMap = new HashMap<>(); + globalUsersMap = new HashMap<>(); - for (LocalAuthMethod fileAuthMethod : authMethods) { + for (LocalAuthMethod fileAuthMethod : authMethods) { - String userFilePath = fileAuthMethod.getUserFilePath(); + String userFilePath = fileAuthMethod.getUserFilePath(); - LOG.info("* Loading users from file: {}", userFilePath); + LOG.info("* Loading users from file: {}", userFilePath); - try (FileInputStream is = new FileInputStream(userFilePath)) { + try (FileInputStream is = new FileInputStream(userFilePath)) { - Yaml yaml = new Yaml(new CustomClassLoaderConstructor(FileUserRepository.class, - Thread.currentThread().getContextClassLoader())); + Yaml yaml = new Yaml(new CustomClassLoaderConstructor(FileUserRepository.class, + Thread.currentThread().getContextClassLoader())); - FileUserRepository repository = (FileUserRepository) yaml.load(is); + FileUserRepository repository = (FileUserRepository) yaml.load(is); - // Index each entry by its userId - HashMap userMap = new HashMap<>(); - for (User user : repository.getUsers()) { - userMap.put(user.getUserId(), user); - } - globalUsersMap.put(fileAuthMethod, userMap); + // Index each entry by its userId + HashMap userMap = new HashMap<>(); + for (User user : repository.getUsers()) { + userMap.put(user.getUserId(), user); + } + globalUsersMap.put(fileAuthMethod, userMap); - } catch (FileNotFoundException ex) { - throw new InitializationException("Users file not found", ex); - } catch (IOException ex) { - throw new InitializationException("Impossible to parse users file", ex); - } + } catch (FileNotFoundException ex) { + throw new InitializationException("Users file not found", ex); + } catch (IOException ex) { + throw new InitializationException("Impossible to parse users file", ex); + } - fileAuthMethodsMap.put(fileAuthMethod.getName(), fileAuthMethod); - } + fileAuthMethodsMap.put(fileAuthMethod.getName(), fileAuthMethod); + } - register(authMethods, authenticationService); + register(authMethods, authenticationService); - LOG.info("* File Authentication Service initialized"); + LOG.info("* File Authentication Service initialized"); - } + } - public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, TransactionData transactionData) { - LocalAuthMethod fileAuthMethod = (LocalAuthMethod) authMethod; - UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; + LocalAuthMethod fileAuthMethod = (LocalAuthMethod) authMethod; + UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; - String userId = userPwAuthentication.getUserId(); - String password = userPwAuthentication.getPassword(); + String userId = userPwAuthentication.getUserId(); + String password = userPwAuthentication.getPassword(); - if (userId == null || password == null) { - LOG.error("UserId or password is empty"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + if (userId == null || password == null) { + LOG.error("UserId or password is empty"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - User user = globalUsersMap.get(fileAuthMethod).get(userId); + User user = globalUsersMap.get(fileAuthMethod).get(userId); - if (user == null) { - LOG.error("Unknown user: {}", userPwAuthentication.getUserId()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + if (user == null) { + LOG.error("Unknown user: {}", userPwAuthentication.getUserId()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - String hashedPassword = user.getPassword(); + String hashedPassword = user.getPassword(); - // If the password doesn't start with $, it is not hashed - // $2a indicates a Bcrypt hash - if (hashedPassword.charAt(0) != '$' && hashedPassword.equals(password) - || hashedPassword.startsWith("$2a") && BCrypt.checkpw(password, hashedPassword)) { + // If the password doesn't start with $, it is not hashed + // $2a indicates a Bcrypt hash + if (hashedPassword.charAt(0) != '$' && hashedPassword.equals(password) + || hashedPassword.startsWith("$2a") && BCrypt.checkpw(password, hashedPassword)) { - LOG.info("User {} successfully authenticated with {} method", user.getUserId(), fileAuthMethod.getName()); + LOG.info("User {} successfully authenticated with {} method", user.getUserId(), fileAuthMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) - .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); - } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) + .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); + } - LOG.info("Failed authentication for user {} with {} method", user.getUserId(), fileAuthMethod.getName()); + LOG.info("Failed authentication for user {} with {} method", user.getUserId(), fileAuthMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - private void register(List authMethods, AuthenticationService authenticationService) { + private void register(List authMethods, AuthenticationService authenticationService) { - for (LocalAuthMethod authMethod : authMethods) { + for (LocalAuthMethod authMethod : authMethods) { - LOG.debug("* Registering authentication method {}", authMethod.getName()); + LOG.debug("* Registering authentication method {}", authMethod.getName()); - authenticationService.registerExplicit(authMethod, this); - } - } + authenticationService.registerExplicit(authMethod, this); + } + } - @Override - public boolean accepts(Authentication authentication) { - return authentication instanceof UserPasswordAuthentication; - } + @Override + public boolean accepts(Authentication authentication) { + return authentication instanceof UserPasswordAuthentication; + } } diff --git a/src/main/java/net/identio/server/service/authentication/local/User.java b/src/main/java/net/identio/server/service/authentication/local/User.java index 2f8d4bf..f696e63 100644 --- a/src/main/java/net/identio/server/service/authentication/local/User.java +++ b/src/main/java/net/identio/server/service/authentication/local/User.java @@ -1,43 +1,44 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.local; public class User { - private String userId; - private String password; + private String userId; + private String password; - public String getUserId() { - return userId; - } + public String getUserId() { + return userId; + } - public void setUserId(String userId) { - this.userId = userId; - } + public void setUserId(String userId) { + this.userId = userId; + } - public String getPassword() { - return password; - } + public String getPassword() { + return password; + } - public void setPassword(String password) { - this.password = password; - } + public void setPassword(String password) { + this.password = password; + } } diff --git a/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java index dea4998..5419165 100644 --- a/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java +++ b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResult.java @@ -25,74 +25,74 @@ public class AuthenticationResult { - private AuthenticationResultStatus status; - private String errorStatus; - private String challengeType; - private String challengeValue; - private String userId; - private AuthMethod authMethod; - private AuthLevel authLevel; - - public AuthenticationResultStatus getStatus() { - return status; - } - - public AuthenticationResult setStatus(AuthenticationResultStatus status) { - this.status = status; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public AuthenticationResult setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public String getChallengeType() { - return challengeType; - } - - public AuthenticationResult setChallengeType(String challengeType) { - this.challengeType = challengeType; - return this; - } - - public String getChallengeValue() { - return challengeValue; - } - - public AuthenticationResult setChallengeValue(String challengeValue) { - this.challengeValue = challengeValue; - return this; - } - - public String getUserId() { - return userId; - } - - public AuthenticationResult setUserId(String userId) { - this.userId = userId; - return this; - } - - public AuthLevel getAuthLevel() { - return authLevel; - } - - public AuthenticationResult setAuthLevel(AuthLevel authLevel) { - this.authLevel = authLevel; - return this; - } - - public AuthMethod getAuthMethod() { - return authMethod; - } - - public AuthenticationResult setAuthMethod(AuthMethod authMethod) { - this.authMethod = authMethod; - return this; - } + private AuthenticationResultStatus status; + private String errorStatus; + private String challengeType; + private String challengeValue; + private String userId; + private AuthMethod authMethod; + private AuthLevel authLevel; + + public AuthenticationResultStatus getStatus() { + return status; + } + + public AuthenticationResult setStatus(AuthenticationResultStatus status) { + this.status = status; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public AuthenticationResult setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public String getChallengeType() { + return challengeType; + } + + public AuthenticationResult setChallengeType(String challengeType) { + this.challengeType = challengeType; + return this; + } + + public String getChallengeValue() { + return challengeValue; + } + + public AuthenticationResult setChallengeValue(String challengeValue) { + this.challengeValue = challengeValue; + return this; + } + + public String getUserId() { + return userId; + } + + public AuthenticationResult setUserId(String userId) { + this.userId = userId; + return this; + } + + public AuthLevel getAuthLevel() { + return authLevel; + } + + public AuthenticationResult setAuthLevel(AuthLevel authLevel) { + this.authLevel = authLevel; + return this; + } + + public AuthMethod getAuthMethod() { + return authMethod; + } + + public AuthenticationResult setAuthMethod(AuthMethod authMethod) { + this.authMethod = authMethod; + return this; + } } diff --git a/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java index 872fab3..5147fff 100644 --- a/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java +++ b/src/main/java/net/identio/server/service/authentication/model/AuthenticationResultStatus.java @@ -21,5 +21,5 @@ package net.identio.server.service.authentication.model; public enum AuthenticationResultStatus { - SUCCESS, FAIL, CHALLENGE + SUCCESS, FAIL, CHALLENGE } diff --git a/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java b/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java index c1dbcc8..051e6ed 100644 --- a/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java +++ b/src/main/java/net/identio/server/service/authentication/model/UserPasswordAuthentication.java @@ -22,42 +22,42 @@ public class UserPasswordAuthentication implements Authentication { - private String userId; - private String password; - private String challengeResponse; - - public UserPasswordAuthentication(String userId, String password) { - this.userId = userId; - this.password = password; - } - - public UserPasswordAuthentication(String userId, String password, String challenge) { - this.userId = userId; - this.password = password; - this.setChallengeResponse(challenge); - } - - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getChallengeResponse() { - return challengeResponse; - } - - public void setChallengeResponse(String challengeResponse) { - this.challengeResponse = challengeResponse; - } + private String userId; + private String password; + private String challengeResponse; + + public UserPasswordAuthentication(String userId, String password) { + this.userId = userId; + this.password = password; + } + + public UserPasswordAuthentication(String userId, String password, String challenge) { + this.userId = userId; + this.password = password; + this.setChallengeResponse(challenge); + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getChallengeResponse() { + return challengeResponse; + } + + public void setChallengeResponse(String challengeResponse) { + this.challengeResponse = challengeResponse; + } } diff --git a/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java b/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java index f79364b..95f5785 100644 --- a/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java +++ b/src/main/java/net/identio/server/service/authentication/model/X509Authentication.java @@ -24,38 +24,38 @@ public class X509Authentication implements Authentication { - private X509Certificate[] clientAuthCert; - private String userCert; - private String sharedSecret; - - public X509Certificate[] getClientAuthCert() { - return clientAuthCert; - } - - public void setClientAuthCert(X509Certificate[] certificates) { - this.clientAuthCert = certificates; - } - - public String getUserCert() { - return userCert; - } - - public void setUserCert(String userCert) { - this.userCert = userCert; - } - - public String getSharedSecret() { - return sharedSecret; - } - - public void setSharedSecret(String sharedSecret) { - this.sharedSecret = sharedSecret; - } - - public X509Authentication(X509Certificate[] clientAuthCert, - String userCert, String sharedSecret) { - this.clientAuthCert = clientAuthCert; - this.userCert = userCert; - this.sharedSecret = sharedSecret; - } + private X509Certificate[] clientAuthCert; + private String userCert; + private String sharedSecret; + + public X509Certificate[] getClientAuthCert() { + return clientAuthCert; + } + + public void setClientAuthCert(X509Certificate[] certificates) { + this.clientAuthCert = certificates; + } + + public String getUserCert() { + return userCert; + } + + public void setUserCert(String userCert) { + this.userCert = userCert; + } + + public String getSharedSecret() { + return sharedSecret; + } + + public void setSharedSecret(String sharedSecret) { + this.sharedSecret = sharedSecret; + } + + public X509Authentication(X509Certificate[] clientAuthCert, + String userCert, String sharedSecret) { + this.clientAuthCert = clientAuthCert; + this.userCert = userCert; + this.sharedSecret = sharedSecret; + } } diff --git a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java index 6441cf2..fa27c2e 100644 --- a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.radius; @@ -51,202 +52,202 @@ License, or (at your option) any later version. @Scope("singleton") public class RadiusAuthenticationProvider implements AuthenticationProvider { - private static final Logger LOG = LoggerFactory.getLogger(RadiusAuthenticationProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(RadiusAuthenticationProvider.class); - private HashMap radiusAuthMethodsMap = new HashMap(); + private HashMap radiusAuthMethodsMap = new HashMap(); - private int currentHostIndex; + private int currentHostIndex; - @Autowired - public RadiusAuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) { + @Autowired + public RadiusAuthenticationProvider(ConfigurationService configurationService, + AuthenticationService authenticationService) { - List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() - .getRadiusAuthMethods(); + List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() + .getRadiusAuthMethods(); - if (authMethods == null) - return; + if (authMethods == null) + return; - LOG.debug("Initializing Radius Authentication Service"); + LOG.debug("Initializing Radius Authentication Service"); - for (RadiusAuthMethod radiusAuthMethod : authMethods) { + for (RadiusAuthMethod radiusAuthMethod : authMethods) { - LOG.debug("* Data Source: {}", radiusAuthMethod.getName()); + LOG.debug("* Data Source: {}", radiusAuthMethod.getName()); - radiusAuthMethodsMap.put(radiusAuthMethod.getName(), radiusAuthMethod); - } + radiusAuthMethodsMap.put(radiusAuthMethod.getName(), radiusAuthMethod); + } - register(authMethods, authenticationService); + register(authMethods, authenticationService); - LOG.info("* Radius Authentication Service initialized"); + LOG.info("* Radius Authentication Service initialized"); - } + } - public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData) { - RadiusAuthMethod radiusAuthMethod = (RadiusAuthMethod) authMethod; - UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; + RadiusAuthMethod radiusAuthMethod = (RadiusAuthMethod) authMethod; + UserPasswordAuthentication userPwAuthentication = (UserPasswordAuthentication) authentication; - String userId = userPwAuthentication.getUserId(); - String password = userPwAuthentication.getPassword(); - String challengeResponse = userPwAuthentication.getChallengeResponse(); + String userId = userPwAuthentication.getUserId(); + String password = userPwAuthentication.getPassword(); + String challengeResponse = userPwAuthentication.getChallengeResponse(); - try { - return authenticate(radiusAuthMethod, userId, password, challengeResponse); - } catch (RadiusException e) { - try { - LOG.error("Error when contacting RadiusServer server {}", - radiusAuthMethod.getRadiusHost()[currentHostIndex]); + try { + return authenticate(radiusAuthMethod, userId, password, challengeResponse); + } catch (RadiusException e) { + try { + LOG.error("Error when contacting RadiusServer server {}", + radiusAuthMethod.getRadiusHost()[currentHostIndex]); - if (radiusAuthMethod.getRadiusHost().length > 1) { - // Try another server if available - currentHostIndex = currentHostIndex < radiusAuthMethod.getRadiusHost().length - 1 - ? currentHostIndex + 1 : 0; + if (radiusAuthMethod.getRadiusHost().length > 1) { + // Try another server if available + currentHostIndex = currentHostIndex < radiusAuthMethod.getRadiusHost().length - 1 + ? currentHostIndex + 1 : 0; - LOG.error("Switching to Radius server {}", radiusAuthMethod.getRadiusHost()[currentHostIndex]); - } + LOG.error("Switching to Radius server {}", radiusAuthMethod.getRadiusHost()[currentHostIndex]); + } - return authenticate(radiusAuthMethod, userId, password, challengeResponse); - } catch (RadiusException ex) { - LOG.error("An error occurend when authenticating user"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); - } - } - } + return authenticate(radiusAuthMethod, userId, password, challengeResponse); + } catch (RadiusException ex) { + LOG.error("An error occurend when authenticating user"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); + } + } + } - private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, String userId, String password, - String challenge) throws RadiusException { + private AuthenticationResult authenticate(RadiusAuthMethod radiusAuthMethod, String userId, String password, + String challenge) throws RadiusException { - try { + try { - RadiusClient client = new RadiusClient(radiusAuthMethod.getRadiusHost()[currentHostIndex], - radiusAuthMethod.getAuthPort(), radiusAuthMethod.getAccountPort(), - radiusAuthMethod.getSharedSecret(), radiusAuthMethod.getTimeout()); + RadiusClient client = new RadiusClient(radiusAuthMethod.getRadiusHost()[currentHostIndex], + radiusAuthMethod.getAuthPort(), radiusAuthMethod.getAccountPort(), + radiusAuthMethod.getSharedSecret(), radiusAuthMethod.getTimeout()); - RadiusPacket accessRequest = new PapAccessRequest(userId, password); + RadiusPacket accessRequest = new PapAccessRequest(userId, password); - if (challenge != null) { - accessRequest.setAttribute(deserializeAttribute(challenge)); - } + if (challenge != null) { + accessRequest.setAttribute(deserializeAttribute(challenge)); + } - // Send access request - RadiusPacket accessResponse = client.authenticate(accessRequest); + // Send access request + RadiusPacket accessResponse = client.authenticate(accessRequest); - if (accessResponse.getPacketType() == RadiusPacket.ACCESS_ACCEPT) { + if (accessResponse.getPacketType() == RadiusPacket.ACCESS_ACCEPT) { - LOG.info("User {} successfully authenticated with {}", userId, radiusAuthMethod.getName()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) - .setAuthMethod(radiusAuthMethod).setAuthLevel(radiusAuthMethod.getAuthLevel()); - } + LOG.info("User {} successfully authenticated with {}", userId, radiusAuthMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(userId) + .setAuthMethod(radiusAuthMethod).setAuthLevel(radiusAuthMethod.getAuthLevel()); + } - if (accessResponse.getPacketType() == RadiusPacket.ACCESS_CHALLENGE) { + if (accessResponse.getPacketType() == RadiusPacket.ACCESS_CHALLENGE) { - String message = new String( - accessResponse.getAttribute(RadiusAttributeValues.REPLY_MESSAGE).getValue()); + String message = new String( + accessResponse.getAttribute(RadiusAttributeValues.REPLY_MESSAGE).getValue()); - String radiusState = serializeAttribute(accessResponse.getAttribute(RadiusAttributeValues.STATE)); - String challengeType = null; + String radiusState = serializeAttribute(accessResponse.getAttribute(RadiusAttributeValues.STATE)); + String challengeType = null; - LOG.debug("Received challenge: {}", message); + LOG.debug("Received challenge: {}", message); - // We have to parse the reply message from the radius server to - // know what to do + // We have to parse the reply message from the radius server to + // know what to do - // Next token mode - if (message.contains("enter the new tokencode")) { + // Next token mode + if (message.contains("enter the new tokencode")) { - LOG.debug("Radius server asked for the next token code"); - challengeType = "RADIUS_NEXT_TOKEN"; - } - // Next passcode - if (message.contains("enter the new passcode")) { + LOG.debug("Radius server asked for the next token code"); + challengeType = "RADIUS_NEXT_TOKEN"; + } + // Next passcode + if (message.contains("enter the new passcode")) { - LOG.debug("Radius server asked for the next passcode"); - challengeType = "RADIUS_NEXT_PASSCODE"; - } - // New PIN mode - if (message.contains("Enter a new PIN")) { - LOG.debug("Radius server asked for a new PIN"); - challengeType = "RADIUS_NEW_PIN"; - } + LOG.debug("Radius server asked for the next passcode"); + challengeType = "RADIUS_NEXT_PASSCODE"; + } + // New PIN mode + if (message.contains("Enter a new PIN")) { + LOG.debug("Radius server asked for a new PIN"); + challengeType = "RADIUS_NEW_PIN"; + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.CHALLENGE) - .setChallengeType(challengeType).setChallengeValue(radiusState).setUserId(userId); - } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.CHALLENGE) + .setChallengeType(challengeType).setChallengeValue(radiusState).setUserId(userId); + } - if (accessResponse.getPacketType() == RadiusPacket.ACCESS_REJECT) { + if (accessResponse.getPacketType() == RadiusPacket.ACCESS_REJECT) { - if (accessResponse.hasAttribute(RadiusAttributeValues.REPLY_MESSAGE)) { - String message = new String( - accessResponse.getAttribute(RadiusAttributeValues.REPLY_MESSAGE).getValue()); + if (accessResponse.hasAttribute(RadiusAttributeValues.REPLY_MESSAGE)) { + String message = new String( + accessResponse.getAttribute(RadiusAttributeValues.REPLY_MESSAGE).getValue()); - LOG.error("Authentication failed for user {} with {}: {}", userId, radiusAuthMethod.getName(), - message); - } else { - LOG.error("Authentication failed for user {} with {}", userId, radiusAuthMethod.getName()); - } - new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + LOG.error("Authentication failed for user {} with {}: {}", userId, radiusAuthMethod.getName(), + message); + } else { + LOG.error("Authentication failed for user {} with {}", userId, radiusAuthMethod.getName()); + } + new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - } catch (InvalidParameterException | IOException | Base64DecodingException | DataFormatException ex) { - LOG.error("Error when contacting RadiusServer server {}", - radiusAuthMethod.getRadiusHost()[currentHostIndex]); - } + } catch (InvalidParameterException | IOException | Base64DecodingException | DataFormatException ex) { + LOG.error("Error when contacting RadiusServer server {}", + radiusAuthMethod.getRadiusHost()[currentHostIndex]); + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); - } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); + } - private RadiusAttribute deserializeAttribute(String data) - throws Base64DecodingException, IOException, DataFormatException, InvalidParameterException { + private RadiusAttribute deserializeAttribute(String data) + throws Base64DecodingException, IOException, DataFormatException, InvalidParameterException { - byte[] dataBytes = DecodeUtils.decode(data, false); + byte[] dataBytes = DecodeUtils.decode(data, false); - int type = dataBytes[0]; + int type = dataBytes[0]; - int valueLength = dataBytes.length - 2; // HEADER_LENGTH = 2 - byte[] valueBytes = new byte[valueLength]; - System.arraycopy(dataBytes, 2, valueBytes, 0, valueLength); + int valueLength = dataBytes.length - 2; // HEADER_LENGTH = 2 + byte[] valueBytes = new byte[valueLength]; + System.arraycopy(dataBytes, 2, valueBytes, 0, valueLength); - return new RadiusAttribute(type, valueBytes); - } + return new RadiusAttribute(type, valueBytes); + } - private String serializeAttribute(RadiusAttribute attribute) throws InvalidParameterException, IOException { + private String serializeAttribute(RadiusAttribute attribute) throws InvalidParameterException, IOException { - int type = attribute.getType(); - byte[] value = attribute.getValue(); + int type = attribute.getType(); + byte[] value = attribute.getValue(); - byte[] data; + byte[] data; - int length = 2 + value.length;// 2 bytes header - try (ByteArrayOutputStream temp = new ByteArrayOutputStream(length)) { - temp.write(type); - temp.write(length); - temp.write(value); - temp.flush(); - data = temp.toByteArray(); - } catch (IOException ex) { - throw new InvalidParameterException("Error constructing RadiusAttribute"); - } + int length = 2 + value.length;// 2 bytes header + try (ByteArrayOutputStream temp = new ByteArrayOutputStream(length)) { + temp.write(type); + temp.write(length); + temp.write(value); + temp.flush(); + data = temp.toByteArray(); + } catch (IOException ex) { + throw new InvalidParameterException("Error constructing RadiusAttribute"); + } - return DecodeUtils.encode(data, false); - } + return DecodeUtils.encode(data, false); + } - private void register(List authMethods, AuthenticationService authenticationService) { + private void register(List authMethods, AuthenticationService authenticationService) { - for (RadiusAuthMethod authMethod : authMethods) { + for (RadiusAuthMethod authMethod : authMethods) { - LOG.debug("* Registering authentication method {}", authMethod.getName()); + LOG.debug("* Registering authentication method {}", authMethod.getName()); - authenticationService.registerExplicit(authMethod, this); - } - } + authenticationService.registerExplicit(authMethod, this); + } + } - @Override - public boolean accepts(Authentication authentication) { - return authentication instanceof UserPasswordAuthentication; - } + @Override + public boolean accepts(Authentication authentication) { + return authentication instanceof UserPasswordAuthentication; + } } diff --git a/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java index daae1e1..fc2add5 100644 --- a/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/saml/SamlAuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.saml; @@ -54,243 +55,243 @@ License, or (at your option) any later version. @Service public class SamlAuthenticationProvider implements AuthenticationProvider { - private static final Logger LOG = LoggerFactory.getLogger(SamlAuthenticationProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(SamlAuthenticationProvider.class); - private HashMap remoteIdpValidators; - private HashMap remoteIdpMetadatasByName; + private HashMap remoteIdpValidators; + private HashMap remoteIdpMetadatasByName; - private ConfigurationService configurationService; + private ConfigurationService configurationService; - @Autowired - private SamlService samlService; + @Autowired + private SamlService samlService; - @Autowired - private MetadataService metadataService; + @Autowired + private MetadataService metadataService; - @Autowired - public SamlAuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) throws InitializationException { + @Autowired + public SamlAuthenticationProvider(ConfigurationService configurationService, + AuthenticationService authenticationService) throws InitializationException { - LOG.debug("Initialization of Metadata Service..."); + LOG.debug("Initialization of Metadata Service..."); - this.configurationService = configurationService; + this.configurationService = configurationService; - try { + try { - initRemoteIdpMetadata(); + initRemoteIdpMetadata(); - register(configurationService.getConfiguration().getAuthMethodConfiguration().getSamlAuthMethods(), - authenticationService); + register(configurationService.getConfiguration().getAuthMethodConfiguration().getSamlAuthMethods(), + authenticationService); - } catch (TechnicalException ex) { - throw new InitializationException("Could not initialize Metadata service", ex); - } - } + } catch (TechnicalException ex) { + throw new InitializationException("Could not initialize Metadata service", ex); + } + } - private void initRemoteIdpMetadata() throws TechnicalException { + private void initRemoteIdpMetadata() throws TechnicalException { - IdentioConfiguration config = configurationService.getConfiguration(); + IdentioConfiguration config = configurationService.getConfiguration(); - List samlAuthMethods = config.getAuthMethodConfiguration().getSamlAuthMethods(); - if (samlAuthMethods == null) { - return; - } + List samlAuthMethods = config.getAuthMethodConfiguration().getSamlAuthMethods(); + if (samlAuthMethods == null) { + return; + } - LOG.info("Loading Remote IDP metadata..."); + LOG.info("Loading Remote IDP metadata..."); - remoteIdpValidators = new HashMap<>(); - remoteIdpMetadatasByName = new HashMap<>(); + remoteIdpValidators = new HashMap<>(); + remoteIdpMetadatasByName = new HashMap<>(); - for (SamlAuthMethod authMethod : samlAuthMethods) { + for (SamlAuthMethod authMethod : samlAuthMethods) { - Metadata remoteIdpMetadata = MetadataBuilder.build(new File(authMethod.getMetadata())); - LOG.info("* {}: {}", remoteIdpMetadata.getEntityID(), authMethod.getMetadata()); + Metadata remoteIdpMetadata = MetadataBuilder.build(new File(authMethod.getMetadata())); + LOG.info("* {}: {}", remoteIdpMetadata.getEntityID(), authMethod.getMetadata()); - ArrayList certificates = new ArrayList<>(); + ArrayList certificates = new ArrayList<>(); - for (IdpSsoDescriptor descriptor : remoteIdpMetadata.getIdpSsoDescriptors()) { - certificates.addAll(descriptor.getSigningCertificates()); - } + for (IdpSsoDescriptor descriptor : remoteIdpMetadata.getIdpSsoDescriptors()) { + certificates.addAll(descriptor.getSigningCertificates()); + } - // Check if the metadatas is valid - Validator validator = new Validator(certificates, authMethod.isCertificateCheckEnabled()); + // Check if the metadatas is valid + Validator validator = new Validator(certificates, authMethod.isCertificateCheckEnabled()); - remoteIdpValidators.put(authMethod.getName(), validator); - remoteIdpMetadatasByName.put(authMethod.getName(), remoteIdpMetadata); - } - } + remoteIdpValidators.put(authMethod.getName(), validator); + remoteIdpMetadatasByName.put(authMethod.getName(), remoteIdpMetadata); + } + } - public SamlAuthRequestGenerationResult initRequest(SamlAuthMethod authMethod, ArrayList targetAuthLevels, + public SamlAuthRequestGenerationResult initRequest(SamlAuthMethod authMethod, ArrayList targetAuthLevels, String transactionId) throws SamlException { - Metadata remoteMetadata = remoteIdpMetadatasByName.get(authMethod.getName()); + Metadata remoteMetadata = remoteIdpMetadatasByName.get(authMethod.getName()); - ArrayList requestedAuthContext = new ArrayList<>(); + ArrayList requestedAuthContext = new ArrayList<>(); - HashMap outMap = authMethod.getSamlAuthMap().getOut(); + HashMap outMap = authMethod.getSamlAuthMap().getOut(); - // Find target auth levels - for (AuthLevel targetAuthLevel : targetAuthLevels) { + // Find target auth levels + for (AuthLevel targetAuthLevel : targetAuthLevels) { - String urn = outMap.get(targetAuthLevel); + String urn = outMap.get(targetAuthLevel); - if (urn != null && !requestedAuthContext.contains(urn)) { - requestedAuthContext.add(0, urn); - } + if (urn != null && !requestedAuthContext.contains(urn)) { + requestedAuthContext.add(0, urn); + } - } + } - return samlService.generateAuthentRequest(remoteMetadata, requestedAuthContext, SamlConstants.COMPARISON_EXACT, - transactionId); - } + return samlService.generateAuthentRequest(remoteMetadata, requestedAuthContext, SamlConstants.COMPARISON_EXACT, + transactionId); + } - public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData) { - LOG.info("Validating SAML response from proxy IDP"); + LOG.info("Validating SAML response from proxy IDP"); - SamlAuthentication samlAuthentication = (SamlAuthentication) authentication; + SamlAuthentication samlAuthentication = (SamlAuthentication) authentication; - String decodedSamlResponse; - try { - decodedSamlResponse = new String(DecodeUtils.decode(samlAuthentication.getResponse(), false)); + String decodedSamlResponse; + try { + decodedSamlResponse = new String(DecodeUtils.decode(samlAuthentication.getResponse(), false)); - SamlAuthMethod samlAuthMethod = (SamlAuthMethod) authMethod; + SamlAuthMethod samlAuthMethod = (SamlAuthMethod) authMethod; - Metadata idpMetadata = metadataService.getIdpMetadata(); - Validator remoteValidator = remoteIdpValidators.get(samlAuthMethod.getName()); + Metadata idpMetadata = metadataService.getIdpMetadata(); + Validator remoteValidator = remoteIdpValidators.get(samlAuthMethod.getName()); - AuthentResponse response = AuthentResponseBuilder.getInstance().build(decodedSamlResponse); - Assertion assertion = response.getAssertion(); + AuthentResponse response = AuthentResponseBuilder.getInstance().build(decodedSamlResponse); + Assertion assertion = response.getAssertion(); - // Verify the status of the response - String responseStatusCode = response.getStatusCode(); + // Verify the status of the response + String responseStatusCode = response.getStatusCode(); - if (!SamlConstants.STATUS_SUCCESS.equals(responseStatusCode)) { - LOG.error("* Authentication rejected by proxy IDP"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_REJECTED); - } - - // Verify the presence of a SAML Assertion - if (assertion == null) { - LOG.error("* No assertion found in response"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } - - // Check inResponseTo attribute coherence - if (!transactionData.getSamlProxyRequestId().equals(assertion.getInResponseTo())) { - LOG.error("* InResponseTo ID doesn't match request ID"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } + if (!SamlConstants.STATUS_SUCCESS.equals(responseStatusCode)) { + LOG.error("* Authentication rejected by proxy IDP"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_REJECTED); + } + + // Verify the presence of a SAML Assertion + if (assertion == null) { + LOG.error("* No assertion found in response"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } + + // Check inResponseTo attribute coherence + if (!transactionData.getSamlProxyRequestId().equals(assertion.getInResponseTo())) { + LOG.error("* InResponseTo ID doesn't match request ID"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } - // Check that the response user ID matches the ID in session - if (assertion.getSubjectNameID() == null - || !assertion.getSubjectNameID().equals(transactionData.getUserSession().getUserId())) { - LOG.error("* Audience in assertion doesn't match IDP EntityID"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } + // Check that the response user ID matches the ID in session + if (assertion.getSubjectNameID() == null + || !assertion.getSubjectNameID().equals(transactionData.getUserSession().getUserId())) { + LOG.error("* Audience in assertion doesn't match IDP EntityID"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } - // Check that the recipient of the assertion is the IDP - if (assertion.getAudienceRestriction() == null - || !assertion.getAudienceRestriction().equals(idpMetadata.getEntityID())) { - LOG.error("* Audience in assertion doesn't match IDP EntityID"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } + // Check that the recipient of the assertion is the IDP + if (assertion.getAudienceRestriction() == null + || !assertion.getAudienceRestriction().equals(idpMetadata.getEntityID())) { + LOG.error("* Audience in assertion doesn't match IDP EntityID"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } - // Check recipient and destination - boolean validation = false; - String recipient = assertion.getRecipient(); - String destination = response.getDestination(); + // Check recipient and destination + boolean validation = false; + String recipient = assertion.getRecipient(); + String destination = response.getDestination(); - if (recipient == null) { - LOG.error("* No recipient specified in assertion"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + if (recipient == null) { + LOG.error("* No recipient specified in assertion"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } + } - if (destination == null) { - LOG.error("* No destination specified in response"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } + if (destination == null) { + LOG.error("* No destination specified in response"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } - for (Endpoint endpoint : idpMetadata.getSpSsoDescriptors().get(0).getAssertionConsumerServices()) { - String location = endpoint.getLocation(); + for (Endpoint endpoint : idpMetadata.getSpSsoDescriptors().get(0).getAssertionConsumerServices()) { + String location = endpoint.getLocation(); - if (location.equals(recipient) && location.equals(destination)) { - validation = true; - } - } - - if (!validation) { - LOG.error("* Recipient or destination in response doesn't match an IDP endpoint"); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } - - // Check assertion time conditions - try { - remoteValidator.checkConditions(assertion); - } catch (InvalidAssertionException ex) { - LOG.error("* Conditions in the assertion are not valid: {}", ex.getMessage()); - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } - - try { - validation = remoteValidator.validate(response); - - } catch (UnsignedSAMLObjectException | NoSuchAlgorithmException | UntrustedSignerException - | InvalidSignatureException ex) { - - LOG.error("* Response is invalid: {}", ex.getMessage()); - LOG.debug("* Detailed stacktrace:", ex); - - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); - } - - // If the assertion is valid - if (validation) { - LOG.info("* Response is valid"); - - // Mapping the authentication level - AuthLevel authLevel = samlAuthMethod.getSamlAuthMap().getIn().get(assertion.getAuthnContext()); - - return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS) - .setUserId(assertion.getSubjectNameID()).setAuthMethod(samlAuthMethod).setAuthLevel(authLevel); - } - } catch (Base64DecodingException | IOException | DataFormatException | TechnicalException - | InvalidAuthentResponseException | InvalidAssertionException ex) { - LOG.error("* Error when parsing SAML Response: {}", ex.getMessage()); - } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); - } - - private void register(List authMethods, AuthenticationService authenticationService) { - - if (authMethods == null) { - return; - } - - for (SamlAuthMethod authMethod : authMethods) { - - LOG.debug("* Registering authentication method {}", authMethod.getName()); - - authenticationService.registerExplicit(authMethod, this); - } - } - - @Override - public boolean accepts(Authentication authentication) { - return authentication instanceof SamlAuthentication; - } + if (location.equals(recipient) && location.equals(destination)) { + validation = true; + } + } + + if (!validation) { + LOG.error("* Recipient or destination in response doesn't match an IDP endpoint"); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } + + // Check assertion time conditions + try { + remoteValidator.checkConditions(assertion); + } catch (InvalidAssertionException ex) { + LOG.error("* Conditions in the assertion are not valid: {}", ex.getMessage()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } + + try { + validation = remoteValidator.validate(response); + + } catch (UnsignedSAMLObjectException | NoSuchAlgorithmException | UntrustedSignerException + | InvalidSignatureException ex) { + + LOG.error("* Response is invalid: {}", ex.getMessage()); + LOG.debug("* Detailed stacktrace:", ex); + + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.AUTH_SAML_INVALID_RESPONSE); + } + + // If the assertion is valid + if (validation) { + LOG.info("* Response is valid"); + + // Mapping the authentication level + AuthLevel authLevel = samlAuthMethod.getSamlAuthMap().getIn().get(assertion.getAuthnContext()); + + return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS) + .setUserId(assertion.getSubjectNameID()).setAuthMethod(samlAuthMethod).setAuthLevel(authLevel); + } + } catch (Base64DecodingException | IOException | DataFormatException | TechnicalException + | InvalidAuthentResponseException | InvalidAssertionException ex) { + LOG.error("* Error when parsing SAML Response: {}", ex.getMessage()); + } + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.TECHNICAL_ERROR); + } + + private void register(List authMethods, AuthenticationService authenticationService) { + + if (authMethods == null) { + return; + } + + for (SamlAuthMethod authMethod : authMethods) { + + LOG.debug("* Registering authentication method {}", authMethod.getName()); + + authenticationService.registerExplicit(authMethod, this); + } + } + + @Override + public boolean accepts(Authentication authentication) { + return authentication instanceof SamlAuthentication; + } } diff --git a/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java index 1ed72d7..2b204de 100644 --- a/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/x509/X509AuthenticationProvider.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authentication.x509; @@ -53,218 +54,218 @@ License, or (at your option) any later version. @Scope("singleton") public class X509AuthenticationProvider implements AuthenticationProvider { - private static final Logger LOG = LoggerFactory.getLogger(X509AuthenticationProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(X509AuthenticationProvider.class); + + private HashMap conditionExpressions = new HashMap<>(); + private HashMap uidExpressions = new HashMap<>(); - private HashMap conditionExpressions = new HashMap<>(); - private HashMap uidExpressions = new HashMap<>(); + private HashMap clientTrusts = new HashMap<>(); + private HashMap proxyTrusts = new HashMap<>(); - private HashMap clientTrusts = new HashMap<>(); - private HashMap proxyTrusts = new HashMap<>(); + private List serverTrusts = new ArrayList<>(); - private List serverTrusts = new ArrayList<>(); + @Autowired + public X509AuthenticationProvider(ConfigurationService configurationService, + AuthenticationService authenticationService) throws InitializationException { - @Autowired - public X509AuthenticationProvider(ConfigurationService configurationService, - AuthenticationService authenticationService) throws InitializationException { + List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() + .getX509AuthMethods(); - List authMethods = configurationService.getConfiguration().getAuthMethodConfiguration() - .getX509AuthMethods(); + if (authMethods == null) + return; - if (authMethods == null) - return; + LOG.debug("Initializing X509 Authentication Service"); - LOG.debug("Initializing X509 Authentication Service"); + // + for (X509AuthMethod authMethod : authMethods) { - // - for (X509AuthMethod authMethod : authMethods) { + LOG.debug("* Method: {}", authMethod.getName()); - LOG.debug("* Method: {}", authMethod.getName()); + cacheSpelExpressions(authMethod); + cacheCertificates(authMethod); + } - cacheSpelExpressions(authMethod); - cacheCertificates(authMethod); - } + register(authMethods, authenticationService); - register(authMethods, authenticationService); + LOG.info("* X509 Authentication Service initialized"); - LOG.info("* X509 Authentication Service initialized"); + } - } + private void cacheSpelExpressions(X509AuthMethod authMethod) { - private void cacheSpelExpressions(X509AuthMethod authMethod) { + SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, + Thread.currentThread().getContextClassLoader()); - SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, - Thread.currentThread().getContextClassLoader()); + ExpressionParser parser = new SpelExpressionParser(config); - ExpressionParser parser = new SpelExpressionParser(config); + conditionExpressions.put(authMethod, parser.parseExpression(authMethod.getConditionExpression())); + uidExpressions.put(authMethod, parser.parseExpression(authMethod.getUidExpression())); + } - conditionExpressions.put(authMethod, parser.parseExpression(authMethod.getConditionExpression())); - uidExpressions.put(authMethod, parser.parseExpression(authMethod.getUidExpression())); - } + private void cacheCertificates(X509AuthMethod authMethod) throws InitializationException { - private void cacheCertificates(X509AuthMethod authMethod) throws InitializationException { + try { - try { + if (authMethod.getClientCertTrust() != null) { - if (authMethod.getClientCertTrust() != null) { + X509Certificate cert = SecurityUtils.parseCertificate(authMethod.getClientCertTrust()); + clientTrusts.put(authMethod, cert); - X509Certificate cert = SecurityUtils.parseCertificate(authMethod.getClientCertTrust()); - clientTrusts.put(authMethod, cert); + if (authMethod.getSecurity().equals("native")) { + serverTrusts.add(cert); + } + } - if (authMethod.getSecurity().equals("native")) { - serverTrusts.add(cert); - } - } + if (authMethod.getProxyCertTrust() != null) { - if (authMethod.getProxyCertTrust() != null) { + X509Certificate cert = SecurityUtils.parseCertificate(authMethod.getProxyCertTrust()); + proxyTrusts.put(authMethod, cert); - X509Certificate cert = SecurityUtils.parseCertificate(authMethod.getProxyCertTrust()); - proxyTrusts.put(authMethod, cert); + serverTrusts.add(cert); + } - serverTrusts.add(cert); - } + } catch (CertificateException | IOException e) { + throw new InitializationException("Error when parsing certificates for authMethod " + authMethod, e); + } + } - } catch (CertificateException | IOException e) { - throw new InitializationException("Error when parsing certificates for authMethod " + authMethod, e); - } - } + public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, + TransactionData transactionData) { - public AuthenticationResult validate(AuthMethod authMethod, Authentication authentication, - TransactionData transactionData) { + X509AuthMethod x509AuthMethod = (X509AuthMethod) authMethod; + X509Authentication x509Authentication = (X509Authentication) authentication; - X509AuthMethod x509AuthMethod = (X509AuthMethod) authMethod; - X509Authentication x509Authentication = (X509Authentication) authentication; + X509Certificate userCertificate; + try { + userCertificate = getUserCertificate(x509AuthMethod, x509Authentication); - X509Certificate userCertificate; - try { - userCertificate = getUserCertificate(x509AuthMethod, x509Authentication); + LOG.debug("Checking X509 certificate user authentication"); - LOG.debug("Checking X509 certificate user authentication"); + // Check against client trust + if (!userCertificate.getIssuerX500Principal() + .equals(clientTrusts.get(x509AuthMethod).getSubjectX500Principal())) { + LOG.error("User certificate rejected: Not emitted by the trusted issuer of method {}", + authMethod.getName()); - // Check against client trust - if (!userCertificate.getIssuerX500Principal() - .equals(clientTrusts.get(x509AuthMethod).getSubjectX500Principal())) { - LOG.error("User certificate rejected: Not emitted by the trusted issuer of method {}", - authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + // Check expressions + Expression uidExpression = uidExpressions.get(authMethod); + Expression conditionExpression = conditionExpressions.get(authMethod); - // Check expressions - Expression uidExpression = uidExpressions.get(authMethod); - Expression conditionExpression = conditionExpressions.get(authMethod); + // Create evaluation context + StandardEvaluationContext certContext = new StandardEvaluationContext(userCertificate); - // Create evaluation context - StandardEvaluationContext certContext = new StandardEvaluationContext(userCertificate); + if (conditionExpression.getValue(certContext, Boolean.class)) { + String uid = uidExpression.getValue(certContext, String.class); - if (conditionExpression.getValue(certContext, Boolean.class)) { - String uid = uidExpression.getValue(certContext, String.class); + if (uid != null) { - if (uid != null) { + LOG.info("User {} successfully authenticated with method {}", uid, authMethod.getName()); - LOG.info("User {} successfully authenticated with method {}", uid, authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(uid) + .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); + } + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.SUCCESS).setUserId(uid) - .setAuthMethod(authMethod).setAuthLevel(authMethod.getAuthLevel()); - } - } + } catch (CertificateException | ConfigurationException ex) { + LOG.error("Error when parsing user certificate: {}", ex.getMessage()); + LOG.debug("* Detailed Stacktrace: ", ex); + } - } catch (CertificateException | ConfigurationException ex) { - LOG.error("Error when parsing user certificate: {}", ex.getMessage()); - LOG.debug("* Detailed Stacktrace: ", ex); - } + LOG.info("Could not validate user certificate with method {}", authMethod.getName()); - LOG.info("Could not validate user certificate with method {}", authMethod.getName()); + return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) + .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); + } - return new AuthenticationResult().setStatus(AuthenticationResultStatus.FAIL) - .setErrorStatus(AuthenticationErrorStatus.INVALID_CREDENTIALS); - } + private void register(List authMethods, AuthenticationService authenticationService) { - private void register(List authMethods, AuthenticationService authenticationService) { + for (X509AuthMethod authMethod : authMethods) { - for (X509AuthMethod authMethod : authMethods) { + LOG.debug("* Registering authentication method {}", authMethod.getName()); - LOG.debug("* Registering authentication method {}", authMethod.getName()); + authenticationService.registerTransparent(authMethod, this); + } + } - authenticationService.registerTransparent(authMethod, this); - } - } + @Override + public boolean accepts(Authentication authentication) { + return authentication instanceof X509Authentication; + } - @Override - public boolean accepts(Authentication authentication) { - return authentication instanceof X509Authentication; - } + public List getServerTrusts() { + return serverTrusts; + } - public List getServerTrusts() { - return serverTrusts; - } + private X509Certificate getUserCertificate(X509AuthMethod authMethod, X509Authentication authentication) + throws CertificateException, ConfigurationException { - private X509Certificate getUserCertificate(X509AuthMethod authMethod, X509Authentication authentication) - throws CertificateException, ConfigurationException { + X509Certificate userCertificate = null; - X509Certificate userCertificate = null; + switch (authMethod.getSecurity()) { - switch (authMethod.getSecurity()) { + // Native SSL authentication: the client auth certificate is the user + // certificate + case "native": - // Native SSL authentication: the client auth certificate is the user - // certificate - case "native": + userCertificate = authentication.getClientAuthCert()[0]; + break; - userCertificate = authentication.getClientAuthCert()[0]; - break; + // Shared secret between the SSL endpoint and the server. The + // certificate is provided via a header + // Check that a user cert is provided and that the shared secret is + // valid + case "shared-secret": - // Shared secret between the SSL endpoint and the server. The - // certificate is provided via a header - // Check that a user cert is provided and that the shared secret is - // valid - case "shared-secret": + if (!authMethod.getSharedSecret().equals(authentication.getSharedSecret())) { + throw new ConfigurationException("Provided shared secret is invalid"); + } - if (!authMethod.getSharedSecret().equals(authentication.getSharedSecret())) { - throw new ConfigurationException("Provided shared secret is invalid"); - } + if (authentication.getUserCert() != null) { - if (authentication.getUserCert() != null) { + userCertificate = parseUserCertificate(authentication.getUserCert(), authMethod.isApacheFix()); + } + break; - userCertificate = parseUserCertificate(authentication.getUserCert(), authMethod.isApacheFix()); - } - break; + // Certificate is protected by a 2-way SSL authentication between + // endpoint and the server + // Check that client ssl certificate dn and issuer dn are valid + case "ssl": - // Certificate is protected by a 2-way SSL authentication between - // endpoint and the server - // Check that client ssl certificate dn and issuer dn are valid - case "ssl": + X509Certificate clientAuthCert = authentication.getClientAuthCert()[0]; - X509Certificate clientAuthCert = authentication.getClientAuthCert()[0]; + if (authentication.getUserCert() != null + && authMethod.getProxyCertDn().equals(clientAuthCert.getSubjectX500Principal().getName()) + && proxyTrusts.get(authMethod).getSubjectX500Principal() + .equals(clientAuthCert.getIssuerX500Principal())) { - if (authentication.getUserCert() != null - && authMethod.getProxyCertDn().equals(clientAuthCert.getSubjectX500Principal().getName()) - && proxyTrusts.get(authMethod).getSubjectX500Principal() - .equals(clientAuthCert.getIssuerX500Principal())) { + userCertificate = parseUserCertificate(authentication.getUserCert(), authMethod.isApacheFix()); + } + break; - userCertificate = parseUserCertificate(authentication.getUserCert(), authMethod.isApacheFix()); - } - break; + default: + throw new ConfigurationException("Unknown X509 authentication security " + authMethod.getSecurity()); + } - default: - throw new ConfigurationException("Unknown X509 authentication security " + authMethod.getSecurity()); - } + return userCertificate; + } - return userCertificate; - } + private X509Certificate parseUserCertificate(String userCert, boolean apacheFix) throws CertificateException { - private X509Certificate parseUserCertificate(String userCert, boolean apacheFix) throws CertificateException { + String fixedUserCert = userCert; - String fixedUserCert = userCert; - - // Fix for Apache that replaces newlines by spaces in headers - if (apacheFix) { + // Fix for Apache that replaces newlines by spaces in headers + if (apacheFix) { - fixedUserCert = fixedUserCert.replaceAll("-----BEGIN CERTIFICATE----- ", "") - .replaceAll(" -----END CERTIFICATE-----", "").replaceAll(" ", "\r\n"); - fixedUserCert = "-----BEGIN CERTIFICATE-----\r\n" + fixedUserCert + "\r\n-----END CERTIFICATE-----"; - } + fixedUserCert = fixedUserCert.replaceAll("-----BEGIN CERTIFICATE----- ", "") + .replaceAll(" -----END CERTIFICATE-----", "").replaceAll(" ", "\r\n"); + fixedUserCert = "-----BEGIN CERTIFICATE-----\r\n" + fixedUserCert + "\r\n-----END CERTIFICATE-----"; + } - return (X509Certificate) CertificateFactory.getInstance("X.509") - .generateCertificate(new ByteArrayInputStream(fixedUserCert.getBytes())); - } + return (X509Certificate) CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(fixedUserCert.getBytes())); + } } diff --git a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java index ee88256..7c770f2 100644 --- a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java +++ b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authorization; @@ -35,45 +36,45 @@ License, or (at your option) any later version. @Service public class AuthorizationService { - private static final Logger LOG = LoggerFactory.getLogger(AuthorizationService.class); - - private HashMap scopes; + private static final Logger LOG = LoggerFactory.getLogger(AuthorizationService.class); + + private HashMap scopes; + + @Autowired + public AuthorizationService(ConfigurationService configurationService) { + + scopes = new HashMap<>(); - @Autowired - public AuthorizationService(ConfigurationService configurationService) { + List configuredScopes = configurationService.getConfiguration().getAuthorizationConfiguration().getScopes(); - scopes = new HashMap<>(); + if (configuredScopes == null) { + return; + } - List configuredScopes = configurationService.getConfiguration().getAuthorizationConfiguration().getScopes(); + LOG.info("Initializing Authorization Service"); - if (configuredScopes == null) { - return; - } - - LOG.info("Initializing Authorization Service"); - - for (AuthorizationScope scope : configuredScopes) { - scopes.put(scope.getName(), scope); - } + for (AuthorizationScope scope : configuredScopes) { + scopes.put(scope.getName(), scope); + } - } + } - public List getScopes(List scopeNames) throws UnknownScopeException, NoScopeProvidedException { + public List getScopes(List scopeNames) throws UnknownScopeException, NoScopeProvidedException { - List scopeList = new ArrayList<>(); + List scopeList = new ArrayList<>(); - if (scopeNames.isEmpty()) { - throw new NoScopeProvidedException("Scope list is empty"); - } + if (scopeNames.isEmpty()) { + throw new NoScopeProvidedException("Scope list is empty"); + } - for (String scopeName : scopeNames) { - if (scopes.containsKey(scopeName)) { - scopeList.add(scopes.get(scopeName)); - } else { - throw new UnknownScopeException("Unknown scope: " + scopeName); - } - } - return scopeList; - } + for (String scopeName : scopeNames) { + if (scopes.containsKey(scopeName)) { + scopeList.add(scopes.get(scopeName)); + } else { + throw new UnknownScopeException("Unknown scope: " + scopeName); + } + } + return scopeList; + } } diff --git a/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java b/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java index 5062bd8..2d4bec3 100644 --- a/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java +++ b/src/main/java/net/identio/server/service/authorization/exceptions/NoScopeProvidedException.java @@ -1,14 +1,35 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.authorization.exceptions; public class NoScopeProvidedException extends Exception { - private static final long serialVersionUID = -7605232415378961869L; + private static final long serialVersionUID = -7605232415378961869L; - public NoScopeProvidedException(String s) { - super(s); - } + public NoScopeProvidedException(String s) { + super(s); + } - public NoScopeProvidedException(String s, Throwable e) { - super(s, e); - } + public NoScopeProvidedException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java b/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java index eb35543..d711eb3 100644 --- a/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java +++ b/src/main/java/net/identio/server/service/authorization/exceptions/UnknownScopeException.java @@ -1,14 +1,35 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.authorization.exceptions; public class UnknownScopeException extends Exception { - private static final long serialVersionUID = 3426051627524438530L; + private static final long serialVersionUID = 3426051627524438530L; - public UnknownScopeException(String s) { - super(s); - } + public UnknownScopeException(String s) { + super(s); + } - public UnknownScopeException(String s, Throwable e) { - super(s, e); - } + public UnknownScopeException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java index dc8e4fb..8f739e3 100644 --- a/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java +++ b/src/main/java/net/identio/server/service/authpolicy/AuthPolicyService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.authpolicy; @@ -44,233 +45,233 @@ License, or (at your option) any later version. @Scope("singleton") public class AuthPolicyService { - private static final Logger LOG = LoggerFactory.getLogger(AuthPolicyService.class); + private static final Logger LOG = LoggerFactory.getLogger(AuthPolicyService.class); - private AuthPolicyConfiguration authPolicyConfiguration; - private AuthMethodConfiguration authMethodConfiguration; + private AuthPolicyConfiguration authPolicyConfiguration; + private AuthMethodConfiguration authMethodConfiguration; - private HashMap authLevelByUrn = new HashMap<>(); - private HashMap authLevelByApp = new HashMap<>(); - private HashMap authMethodByName = new HashMap<>(); + private HashMap authLevelByUrn = new HashMap<>(); + private HashMap authLevelByApp = new HashMap<>(); + private HashMap authMethodByName = new HashMap<>(); - @Autowired - public AuthPolicyService(ConfigurationService configurationService) { + @Autowired + public AuthPolicyService(ConfigurationService configurationService) { - LOG.debug("Initialization of auth policy service"); + LOG.debug("Initialization of auth policy service"); - authPolicyConfiguration = configurationService.getConfiguration().getAuthPolicyConfiguration(); - authMethodConfiguration = configurationService.getConfiguration().getAuthMethodConfiguration(); + authPolicyConfiguration = configurationService.getConfiguration().getAuthPolicyConfiguration(); + authMethodConfiguration = configurationService.getConfiguration().getAuthMethodConfiguration(); - // Index auth levels - int index = 0; - for (AuthLevel authLevel : authPolicyConfiguration.getAuthLevels()) { - authLevel.setStrength(index); - authLevelByUrn.put(authLevel.getUrn(), authLevel); - index++; - } + // Index auth levels + int index = 0; + for (AuthLevel authLevel : authPolicyConfiguration.getAuthLevels()) { + authLevel.setStrength(index); + authLevelByUrn.put(authLevel.getUrn(), authLevel); + index++; + } - // Index app-specific auth levels - List appAuthLevels = authPolicyConfiguration.getApplicationSpecificAuthLevel(); + // Index app-specific auth levels + List appAuthLevels = authPolicyConfiguration.getApplicationSpecificAuthLevel(); - if (appAuthLevels != null) { - for (AppAuthLevel appAuthLevel : appAuthLevels) { - authLevelByApp.put(appAuthLevel.getAppName(), appAuthLevel); - } - } + if (appAuthLevels != null) { + for (AppAuthLevel appAuthLevel : appAuthLevels) { + authLevelByApp.put(appAuthLevel.getAppName(), appAuthLevel); + } + } - // Index auth methods - for (AuthMethod authMethod : authMethodConfiguration.getAuthMethods()) { - authMethodByName.put(authMethod.getName(), authMethod); - } + // Index auth methods + for (AuthMethod authMethod : authMethodConfiguration.getAuthMethods()) { + authMethodByName.put(authMethod.getName(), authMethod); + } - } + } - public ArrayList determineTargetAuthLevel(RequestParsingInfo parsingInfo) { + public ArrayList determineTargetAuthLevel(RequestParsingInfo parsingInfo) { - LOG.debug("Determining authentication strategy for request"); + LOG.debug("Determining authentication strategy for request"); - // Determine the authent level to be applied - // If the request is signed, we can trust the requested authentication - // level. - // Otherwise, we apply the auth level specified in the configuration for - // this application - // If none is specified, we apply the default authent level - List requestedAuthLevels = new ArrayList<>(); - String requestedComparison; + // Determine the authent level to be applied + // If the request is signed, we can trust the requested authentication + // level. + // Otherwise, we apply the auth level specified in the configuration for + // this application + // If none is specified, we apply the default authent level + List requestedAuthLevels = new ArrayList<>(); + String requestedComparison; - ArrayList targetAuthLevels = new ArrayList<>(); + ArrayList targetAuthLevels = new ArrayList<>(); - if (parsingInfo.getRequestedAuthLevels() != null) { + if (parsingInfo.getRequestedAuthLevels() != null) { - requestedAuthLevels = parsingInfo.getRequestedAuthLevels(); - requestedComparison = parsingInfo.getAuthLevelComparison(); + requestedAuthLevels = parsingInfo.getRequestedAuthLevels(); + requestedComparison = parsingInfo.getAuthLevelComparison(); - LOG.debug("* Request specify an auth level. Applying requested auth level"); - } else { - // Request doesn't specify a minimum auth level - // , we check if we have a specific auth level - // for this application - AppAuthLevel appAuthLevel = authLevelByApp.get(parsingInfo.getSourceApplicationName()); + LOG.debug("* Request specify an auth level. Applying requested auth level"); + } else { + // Request doesn't specify a minimum auth level + // , we check if we have a specific auth level + // for this application + AppAuthLevel appAuthLevel = authLevelByApp.get(parsingInfo.getSourceApplicationName()); - if (appAuthLevel != null) { + if (appAuthLevel != null) { - AuthLevel selectedAuthLevel = appAuthLevel.getAuthLevel(); - requestedAuthLevels.add(selectedAuthLevel); - requestedComparison = appAuthLevel.getComparison(); + AuthLevel selectedAuthLevel = appAuthLevel.getAuthLevel(); + requestedAuthLevels.add(selectedAuthLevel); + requestedComparison = appAuthLevel.getComparison(); - LOG.debug("* Request does not specify an auth level. Applying app-specific auth level: {} - {}", - requestedComparison, selectedAuthLevel.getName()); - } else { + LOG.debug("* Request does not specify an auth level. Applying app-specific auth level: {} - {}", + requestedComparison, selectedAuthLevel.getName()); + } else { - AuthLevel selectedAuthLevel = authPolicyConfiguration.getDefaultAuthLevel().getAuthLevel(); + AuthLevel selectedAuthLevel = authPolicyConfiguration.getDefaultAuthLevel().getAuthLevel(); - requestedAuthLevels.add(selectedAuthLevel); - requestedComparison = authPolicyConfiguration.getDefaultAuthLevel().getComparison(); + requestedAuthLevels.add(selectedAuthLevel); + requestedComparison = authPolicyConfiguration.getDefaultAuthLevel().getComparison(); - LOG.debug("* Request does not specify an auth level. Applying default auth level: {} - {}", - requestedComparison, selectedAuthLevel.getName()); - } - } + LOG.debug("* Request does not specify an auth level. Applying default auth level: {} - {}", + requestedComparison, selectedAuthLevel.getName()); + } + } - // Determine the target auth levels - for (AuthLevel authLevel : authPolicyConfiguration.getAuthLevels()) { - int strength = authLevel.getStrength(); + // Determine the target auth levels + for (AuthLevel authLevel : authPolicyConfiguration.getAuthLevels()) { + int strength = authLevel.getStrength(); - for (AuthLevel requestedAuthLevel : requestedAuthLevels) { + for (AuthLevel requestedAuthLevel : requestedAuthLevels) { - int requestedStrength = requestedAuthLevel.getStrength(); + int requestedStrength = requestedAuthLevel.getStrength(); - if (SamlConstants.COMPARISON_EXACT.equals(requestedComparison) && strength == requestedStrength - || SamlConstants.COMPARISON_MINIMUM.equals(requestedComparison) - && strength >= requestedStrength - || SamlConstants.COMPARISON_MAXIMUM.equals(requestedComparison) - && strength <= requestedStrength - || SamlConstants.COMPARISON_BETTER.equals(requestedComparison) - && strength > requestedStrength) { - targetAuthLevels.add(authLevel); - } + if (SamlConstants.COMPARISON_EXACT.equals(requestedComparison) && strength == requestedStrength + || SamlConstants.COMPARISON_MINIMUM.equals(requestedComparison) + && strength >= requestedStrength + || SamlConstants.COMPARISON_MAXIMUM.equals(requestedComparison) + && strength <= requestedStrength + || SamlConstants.COMPARISON_BETTER.equals(requestedComparison) + && strength > requestedStrength) { + targetAuthLevels.add(authLevel); + } - } - } + } + } - // Save the required auth levels - return targetAuthLevels; - } + // Save the required auth levels + return targetAuthLevels; + } - public HashSet determineTargetAuthMethods(ArrayList targetAuthLevels) { + public HashSet determineTargetAuthMethods(ArrayList targetAuthLevels) { - HashSet nextAuthMethods = new HashSet<>(); + HashSet nextAuthMethods = new HashSet<>(); - for (AuthMethod authMethod : authMethodConfiguration.getAuthMethods()) { + for (AuthMethod authMethod : authMethodConfiguration.getAuthMethods()) { - if (authMethod instanceof SamlAuthMethod) { + if (authMethod instanceof SamlAuthMethod) { - // Check if the authentication level is supported - HashMap outMap = ((SamlAuthMethod) authMethod).getSamlAuthMap().getOut(); + // Check if the authentication level is supported + HashMap outMap = ((SamlAuthMethod) authMethod).getSamlAuthMap().getOut(); - for (AuthLevel targetAuthLevel : targetAuthLevels) { - if (outMap.containsKey(targetAuthLevel)) { - nextAuthMethods.add(authMethod); - break; - } - } - continue; - } + for (AuthLevel targetAuthLevel : targetAuthLevels) { + if (outMap.containsKey(targetAuthLevel)) { + nextAuthMethods.add(authMethod); + break; + } + } + continue; + } - if (targetAuthLevels.contains(authMethod.getAuthLevel())) { - nextAuthMethods.add(authMethod); - } - } + if (targetAuthLevels.contains(authMethod.getAuthLevel())) { + nextAuthMethods.add(authMethod); + } + } - return nextAuthMethods; - } + return nextAuthMethods; + } - public AuthPolicyDecision checkPreviousAuthSessions(UserSession userSession, - ArrayList targetAuthLevels) { + public AuthPolicyDecision checkPreviousAuthSessions(UserSession userSession, + ArrayList targetAuthLevels) { - LOG.debug("Check previous authentication sessions"); + LOG.debug("Check previous authentication sessions"); - // We check if the user is already authentified with this auth level - for (AuthSession authSession : userSession.getAuthSessions()) { - for (AuthLevel authLevel : targetAuthLevels) { + // We check if the user is already authentified with this auth level + for (AuthSession authSession : userSession.getAuthSessions()) { + for (AuthLevel authLevel : targetAuthLevels) { - if (authSession.getAuthLevel().equals(authLevel)) { + if (authSession.getAuthLevel().equals(authLevel)) { - LOG.debug("* Found compliant auth session"); + LOG.debug("* Found compliant auth session"); - return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) - .setValidatedAuthSession(authSession); - } - } - } + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) + .setValidatedAuthSession(authSession); + } + } + } - LOG.debug("* No compliant auth session found. Asking for an explicit authentication"); - return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); - } + LOG.debug("* No compliant auth session found. Asking for an explicit authentication"); + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); + } - public void checkAllowedAuthMethods(HashSet targetAuthMethods, AuthMethod submittedAuthMethod) - throws UnknownAuthMethodException, AuthMethodNotAllowedException { + public void checkAllowedAuthMethods(HashSet targetAuthMethods, AuthMethod submittedAuthMethod) + throws UnknownAuthMethodException, AuthMethodNotAllowedException { - if (submittedAuthMethod == null) { - throw new UnknownAuthMethodException("Unknown authentication method"); - } + if (submittedAuthMethod == null) { + throw new UnknownAuthMethodException("Unknown authentication method"); + } - if (!targetAuthMethods.contains(submittedAuthMethod)) { - throw new AuthMethodNotAllowedException("Authentication method " + submittedAuthMethod.getName() - + " is not allowed for this transaction"); - } - } + if (!targetAuthMethods.contains(submittedAuthMethod)) { + throw new AuthMethodNotAllowedException("Authentication method " + submittedAuthMethod.getName() + + " is not allowed for this transaction"); + } + } - public AuthPolicyDecision checkAuthPolicyCompliance(UserSession userSession, AuthenticationResult result, - ArrayList targetAuthLevels) { + public AuthPolicyDecision checkAuthPolicyCompliance(UserSession userSession, AuthenticationResult result, + ArrayList targetAuthLevels) { - // Check that the authlevel matches - if (targetAuthLevels.contains(result.getAuthLevel())) { + // Check that the authlevel matches + if (targetAuthLevels.contains(result.getAuthLevel())) { - AuthSession authSession = updateUserSession(userSession, result, result.getAuthLevel()); - return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) - .setValidatedAuthSession(authSession); + AuthSession authSession = updateUserSession(userSession, result, result.getAuthLevel()); + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.OK) + .setValidatedAuthSession(authSession); - } else { - return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); - } - } + } else { + return new AuthPolicyDecision().setStatus(AuthPolicyDecisionStatus.AUTH); + } + } - public AuthLevel getAuthLevelByUrn(String urn) throws UnknownAuthLevelException { + public AuthLevel getAuthLevelByUrn(String urn) throws UnknownAuthLevelException { - AuthLevel authLevel = authLevelByUrn.get(urn); + AuthLevel authLevel = authLevelByUrn.get(urn); - if (authLevel == null) { - LOG.error("Unknown authentication level requested: {}", urn); - throw new UnknownAuthLevelException("Unknown authentication level requested: " + urn); - } + if (authLevel == null) { + LOG.error("Unknown authentication level requested: {}", urn); + throw new UnknownAuthLevelException("Unknown authentication level requested: " + urn); + } - return authLevel; - } + return authLevel; + } - public AuthMethod getAuthMethodByName(String name) throws UnknownAuthMethodException { + public AuthMethod getAuthMethodByName(String name) throws UnknownAuthMethodException { - AuthMethod authMethod = authMethodByName.get(name); + AuthMethod authMethod = authMethodByName.get(name); - if (authMethod == null) { - throw new UnknownAuthMethodException("Unknown authentication method requested: " + name); - } + if (authMethod == null) { + throw new UnknownAuthMethodException("Unknown authentication method requested: " + name); + } - return authMethod; - } + return authMethod; + } - public String getLogo(String authMethodName) { + public String getLogo(String authMethodName) { - try { - return getAuthMethodByName(authMethodName).getLogoFileName(); - } catch (UnknownAuthMethodException e) { - return null; - } - } + try { + return getAuthMethodByName(authMethodName).getLogoFileName(); + } catch (UnknownAuthMethodException e) { + return null; + } + } - private AuthSession updateUserSession(UserSession userSession, AuthenticationResult result, - AuthLevel authLevel) { + private AuthSession updateUserSession(UserSession userSession, AuthenticationResult result, + AuthLevel authLevel) { - return userSession.addAuthSession(result.getUserId(), result.getAuthMethod(), authLevel); - } + return userSession.addAuthSession(result.getUserId(), result.getAuthMethod(), authLevel); + } } diff --git a/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java index 3db1c6d..5a35ecf 100644 --- a/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java +++ b/src/main/java/net/identio/server/service/authpolicy/model/AuthPolicyDecision.java @@ -27,35 +27,35 @@ public class AuthPolicyDecision { - private AuthPolicyDecisionStatus status; - private AuthSession validatedAuthSession; - private HashSet nextAuthMethods; - - public AuthPolicyDecisionStatus getStatus() { - return status; - } - - public AuthPolicyDecision setStatus(AuthPolicyDecisionStatus status) { - this.status = status; - return this; - } - - public AuthSession getValidatedAuthSession() { - return validatedAuthSession; - } - - public AuthPolicyDecision setValidatedAuthSession(AuthSession validatedAuthSession) { - this.validatedAuthSession = validatedAuthSession; - return this; - } - - public HashSet getNextAuthMethods() { - return nextAuthMethods; - } - - public AuthPolicyDecision setNextAuthMethods(HashSet nextAuthMethods) { - this.nextAuthMethods = nextAuthMethods; - return this; - } + private AuthPolicyDecisionStatus status; + private AuthSession validatedAuthSession; + private HashSet nextAuthMethods; + + public AuthPolicyDecisionStatus getStatus() { + return status; + } + + public AuthPolicyDecision setStatus(AuthPolicyDecisionStatus status) { + this.status = status; + return this; + } + + public AuthSession getValidatedAuthSession() { + return validatedAuthSession; + } + + public AuthPolicyDecision setValidatedAuthSession(AuthSession validatedAuthSession) { + this.validatedAuthSession = validatedAuthSession; + return this; + } + + public HashSet getNextAuthMethods() { + return nextAuthMethods; + } + + public AuthPolicyDecision setNextAuthMethods(HashSet nextAuthMethods) { + this.nextAuthMethods = nextAuthMethods; + return this; + } } diff --git a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java index 2c247a9..5fc0f86 100644 --- a/src/main/java/net/identio/server/service/configuration/ConfigurationService.java +++ b/src/main/java/net/identio/server/service/configuration/ConfigurationService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.configuration; @@ -37,107 +38,107 @@ License, or (at your option) any later version. @Service public class ConfigurationService { - private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class); - - private IdentioConfiguration configuration; - private String configFile; - private String publicFqdn; - - @Autowired - public ConfigurationService(@Value("${identio.config}") String configFile, @Value("${identio.public.fqdn}") String publicFqdn) throws InitializationException { - - if (publicFqdn == null) { - throw new InitializationException("No public FQDN specified"); - } - - this.configFile = configFile; - this.publicFqdn = publicFqdn; - - LOG.debug("Loading configuration file: {}", configFile); - - try (FileInputStream is = new FileInputStream(configFile)) { - - Yaml yaml = new Yaml(new CustomClassLoaderConstructor(IdentioConfiguration.class, - Thread.currentThread().getContextClassLoader())); - - // convert json string to object - configuration = (IdentioConfiguration) yaml.load(is); - - setDefaultValues(); - - } catch (FileNotFoundException ex) { - throw new InitializationException("Configuration file not found", ex); - } catch (IOException ex) { - throw new InitializationException("Impossible to parse configuration file", ex); - } - } - - public String getPublicFqdn() { - return publicFqdn; - } - - public IdentioConfiguration getConfiguration() { - return configuration; - } - - private void setDefaultValues() { - - String configDirectoryPath = Paths.get(configFile).getParent().toAbsolutePath().normalize().toString(); - String home = Paths.get(configDirectoryPath).getParent().toString(); - - // Global configuration default values - - if (configuration.getGlobalConfiguration().getSslKeystorePassword() == null) { - configuration.getGlobalConfiguration().setSslKeystorePassword("password"); - } - - if (configuration.getGlobalConfiguration().getSslKeystorePath() == null) { - configuration.getGlobalConfiguration() - .setSslKeystorePath(Paths.get(configDirectoryPath, "ssl-certificate.p12").toString()); - } - - if (configuration.getGlobalConfiguration().getPort() == 0) { - if (configuration.getGlobalConfiguration().isSecure()) { - configuration.getGlobalConfiguration().setPort(10443); - } else { - configuration.getGlobalConfiguration().setPort(10080); - } - } - - if (configuration.getGlobalConfiguration().getSignatureKeystorePath() == null) { - configuration.getGlobalConfiguration() - .setSignatureKeystorePath(Paths.get(configDirectoryPath, "default-sign-certificate.p12").toString()); - } - - if (configuration.getGlobalConfiguration().getSignatureKeystorePassword() == null) { - configuration.getGlobalConfiguration().setSignatureKeystorePassword("password"); - } - - if (configuration.getGlobalConfiguration().getWorkDirectory() == null) { - configuration.getGlobalConfiguration().setWorkDirectory(Paths.get(configDirectoryPath, "work").toString()); - } - - if (configuration.getGlobalConfiguration().getStaticResourcesPath() == null) { - configuration.getGlobalConfiguration().setStaticResourcesPath(Paths.get(home, "ui/").toString()); - } - - // SAML IDP configuration default values - - if (configuration.getSamlIdpConfiguration().getTokenValidityLength() == 0) { - configuration.getSamlIdpConfiguration().setTokenValidityLength(3); - } - - if (configuration.getSamlIdpConfiguration().getSpMetadataDirectory() == null) { - configuration.getSamlIdpConfiguration() - .setSpMetadataDirectory(Paths.get(configDirectoryPath, "trusted-sp").toString()); - } - - // File authentication method - if (configuration.getAuthMethodConfiguration().getLocalAuthMethods() != null) { - configuration.getAuthMethodConfiguration().getLocalAuthMethods().stream() - .filter(x -> x.getUserFilePath() == null) - .forEach(x -> x.setUserFilePath(Paths.get(configDirectoryPath, "users.yml").toString())); - } - - } + private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class); + + private IdentioConfiguration configuration; + private String configFile; + private String publicFqdn; + + @Autowired + public ConfigurationService(@Value("${identio.config}") String configFile, @Value("${identio.public.fqdn}") String publicFqdn) throws InitializationException { + + if (publicFqdn == null) { + throw new InitializationException("No public FQDN specified"); + } + + this.configFile = configFile; + this.publicFqdn = publicFqdn; + + LOG.debug("Loading configuration file: {}", configFile); + + try (FileInputStream is = new FileInputStream(configFile)) { + + Yaml yaml = new Yaml(new CustomClassLoaderConstructor(IdentioConfiguration.class, + Thread.currentThread().getContextClassLoader())); + + // convert json string to object + configuration = (IdentioConfiguration) yaml.load(is); + + setDefaultValues(); + + } catch (FileNotFoundException ex) { + throw new InitializationException("Configuration file not found", ex); + } catch (IOException ex) { + throw new InitializationException("Impossible to parse configuration file", ex); + } + } + + public String getPublicFqdn() { + return publicFqdn; + } + + public IdentioConfiguration getConfiguration() { + return configuration; + } + + private void setDefaultValues() { + + String configDirectoryPath = Paths.get(configFile).getParent().toAbsolutePath().normalize().toString(); + String home = Paths.get(configDirectoryPath).getParent().toString(); + + // Global configuration default values + + if (configuration.getGlobalConfiguration().getSslKeystorePassword() == null) { + configuration.getGlobalConfiguration().setSslKeystorePassword("password"); + } + + if (configuration.getGlobalConfiguration().getSslKeystorePath() == null) { + configuration.getGlobalConfiguration() + .setSslKeystorePath(Paths.get(configDirectoryPath, "ssl-certificate.p12").toString()); + } + + if (configuration.getGlobalConfiguration().getPort() == 0) { + if (configuration.getGlobalConfiguration().isSecure()) { + configuration.getGlobalConfiguration().setPort(10443); + } else { + configuration.getGlobalConfiguration().setPort(10080); + } + } + + if (configuration.getGlobalConfiguration().getSignatureKeystorePath() == null) { + configuration.getGlobalConfiguration() + .setSignatureKeystorePath(Paths.get(configDirectoryPath, "default-sign-certificate.p12").toString()); + } + + if (configuration.getGlobalConfiguration().getSignatureKeystorePassword() == null) { + configuration.getGlobalConfiguration().setSignatureKeystorePassword("password"); + } + + if (configuration.getGlobalConfiguration().getWorkDirectory() == null) { + configuration.getGlobalConfiguration().setWorkDirectory(Paths.get(configDirectoryPath, "work").toString()); + } + + if (configuration.getGlobalConfiguration().getStaticResourcesPath() == null) { + configuration.getGlobalConfiguration().setStaticResourcesPath(Paths.get(home, "ui/").toString()); + } + + // SAML IDP configuration default values + + if (configuration.getSamlIdpConfiguration().getTokenValidityLength() == 0) { + configuration.getSamlIdpConfiguration().setTokenValidityLength(3); + } + + if (configuration.getSamlIdpConfiguration().getSpMetadataDirectory() == null) { + configuration.getSamlIdpConfiguration() + .setSpMetadataDirectory(Paths.get(configDirectoryPath, "trusted-sp").toString()); + } + + // File authentication method + if (configuration.getAuthMethodConfiguration().getLocalAuthMethods() != null) { + configuration.getAuthMethodConfiguration().getLocalAuthMethods().stream() + .filter(x -> x.getUserFilePath() == null) + .forEach(x -> x.setUserFilePath(Paths.get(configDirectoryPath, "users.yml").toString())); + } + + } } diff --git a/src/main/java/net/identio/server/service/dao/MongoDbDao.java b/src/main/java/net/identio/server/service/dao/MongoDbDao.java index c057066..5f45e8f 100644 --- a/src/main/java/net/identio/server/service/dao/MongoDbDao.java +++ b/src/main/java/net/identio/server/service/dao/MongoDbDao.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.dao; diff --git a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java index cdd4daf..145cefb 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthClientRepository.java @@ -1,9 +1,30 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth; import net.identio.server.service.oauth.model.OAuthClient; public interface OAuthClientRepository { - OAuthClient getOAuthClientbyId(String cliendId); - + OAuthClient getOAuthClientbyId(String cliendId); + } diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 2caa02a..4d4d976 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.oauth; diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java index e21cb0c..87b0ae8 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/FileOAuthClientRepository.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth.infrastructure; import net.identio.server.exceptions.InitializationException; @@ -19,49 +40,49 @@ @Service public class FileOAuthClientRepository implements OAuthClientRepository { - private static final Logger LOG = LoggerFactory.getLogger(FileOAuthClientRepository.class); + private static final Logger LOG = LoggerFactory.getLogger(FileOAuthClientRepository.class); + + private HashMap clients; + + @Autowired + public FileOAuthClientRepository(ConfigurationService configurationService) throws InitializationException { - private HashMap clients; - @Autowired - public FileOAuthClientRepository(ConfigurationService configurationService) throws InitializationException { + clients = new HashMap<>(); + String clientFilePath = configurationService.getConfiguration().getoAuthServerConfiguration().getClientFile(); - clients = new HashMap<>(); + if (clientFilePath == null) { + return; + } - String clientFilePath = configurationService.getConfiguration().getoAuthServerConfiguration().getClientFile(); + LOG.info("Initializing File OAUth Client Repository"); - if (clientFilePath == null) { - return; - } - - LOG.info("Initializing File OAUth Client Repository"); + try (FileInputStream is = new FileInputStream(clientFilePath)) { - try (FileInputStream is = new FileInputStream(clientFilePath)) { + Yaml yaml = new Yaml(new CustomClassLoaderConstructor(OAuthClientFile.class, + Thread.currentThread().getContextClassLoader())); - Yaml yaml = new Yaml(new CustomClassLoaderConstructor(OAuthClientFile.class, - Thread.currentThread().getContextClassLoader())); + OAuthClientFile clientFile = (OAuthClientFile) yaml.load(is); - OAuthClientFile clientFile = (OAuthClientFile) yaml.load(is); + for (OAuthClient client : clientFile.getoAuthClients()) { + clients.put(client.getClientId(), client); + } - for (OAuthClient client : clientFile.getoAuthClients()) { - clients.put(client.getClientId(), client); - } + } catch (FileNotFoundException ex) { + throw new InitializationException("OAUth Client Repository file not found", ex); + } catch (IOException ex) { + throw new InitializationException("Impossible to parse OAUth Client Repository file", ex); + } - } catch (FileNotFoundException ex) { - throw new InitializationException("OAUth Client Repository file not found", ex); - } catch (IOException ex) { - throw new InitializationException("Impossible to parse OAUth Client Repository file", ex); - } + LOG.info("* File OAUth Client Repository initialized"); - LOG.info("* File OAUth Client Repository initialized"); + } - } + @Override + public OAuthClient getOAuthClientbyId(String cliendId) { - @Override - public OAuthClient getOAuthClientbyId(String cliendId) { - - return clients.get(cliendId); - } + return clients.get(cliendId); + } } diff --git a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java index 699485a..8bc93a4 100644 --- a/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java +++ b/src/main/java/net/identio/server/service/oauth/infrastructure/OAuthClientFile.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth.infrastructure; import net.identio.server.service.oauth.model.OAuthClient; @@ -6,14 +27,14 @@ public class OAuthClientFile { - private List oAuthClients; + private List oAuthClients; - public List getoAuthClients() { - return oAuthClients; - } + public List getoAuthClients() { + return oAuthClients; + } - public void setoAuthClients(List oAuthClients) { - this.oAuthClients = oAuthClients; - } + public void setoAuthClients(List oAuthClients) { + this.oAuthClients = oAuthClients; + } } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java index 50084c0..0d6c006 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java @@ -23,69 +23,69 @@ import java.util.List; public class OAuthClient { - - private String name; - private String clientId; - private String clientSecret; - private List allowedScopes; - private List responseUri; - private List allowedGrants; - - private boolean needConsent; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getClientSecret() { - return clientSecret; - } - - public void setClientSecret(String clientSecret) { - this.clientSecret = clientSecret; - } - - public List getAllowedScopes() { - return allowedScopes; - } - - public void setAllowedScopes(List allowedScopes) { - this.allowedScopes = allowedScopes; - } - - public List getResponseUri() { - return responseUri; - } - - public void setResponseUri(List responseUri) { - this.responseUri = responseUri; - } - - public List getAllowedGrants() { - return allowedGrants; - } - - public void setAllowedGrants(List allowedGrants) { - this.allowedGrants = allowedGrants; - } - - public boolean isNeedConsent() { - return needConsent; - } - - public void setNeedConsent(boolean needConsent) { - this.needConsent = needConsent; - } + + private String name; + private String clientId; + private String clientSecret; + private List allowedScopes; + private List responseUri; + private List allowedGrants; + + private boolean needConsent; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public List getAllowedScopes() { + return allowedScopes; + } + + public void setAllowedScopes(List allowedScopes) { + this.allowedScopes = allowedScopes; + } + + public List getResponseUri() { + return responseUri; + } + + public void setResponseUri(List responseUri) { + this.responseUri = responseUri; + } + + public List getAllowedGrants() { + return allowedGrants; + } + + public void setAllowedGrants(List allowedGrants) { + this.allowedGrants = allowedGrants; + } + + public boolean isNeedConsent() { + return needConsent; + } + + public void setNeedConsent(boolean needConsent) { + this.needConsent = needConsent; + } } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java index 0236981..0eac589 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth.model; public class OAuthErrors { diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java index bc1d6bd..d89ebb7 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthGrants.java @@ -1,8 +1,29 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth.model; public class OAuthGrants { - - public static final String IMPLICIT = "implicit"; - public static final String AUTHORIZATION_CODE = "code"; - + + public static final String IMPLICIT = "implicit"; + public static final String AUTHORIZATION_CODE = "code"; + } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java index 29b3ce4..e456de1 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthResponseType.java @@ -1,7 +1,28 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.service.oauth.model; public class OAuthResponseType { - - public static final String CODE = "code"; - public static final String TOKEN = "token"; + + public static final String CODE = "code"; + public static final String TOKEN = "token"; } diff --git a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java index 996a2c6..a34d517 100644 --- a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java @@ -167,8 +167,7 @@ public AuthenticationValidationResult handleExplicitAuthentication(String transa } catch (SamlException e) { throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); - } - finally { + } finally { transactionService.removeTransactionData(transactionData); } } diff --git a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java index 4daea4a..45b7944 100644 --- a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java @@ -74,7 +74,7 @@ public RequestValidationResult validateRequest(InboundRequest request, String se switch (parsingInfo.getStatus()) { case FATAL_ERROR: - throw new ValidationException(parsingInfo.getErrorStatus()); + throw new ValidationException(parsingInfo.getErrorStatus()); case RESPONSE_ERROR: try { diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java index e141f33..cda1adf 100644 --- a/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/ServerException.java @@ -22,13 +22,13 @@ public class ServerException extends Exception { - private static final long serialVersionUID = 3342749474880290649L; + private static final long serialVersionUID = 3342749474880290649L; - public ServerException(String s) { - super(s); - } + public ServerException(String s) { + super(s); + } - public ServerException(String s, Throwable e) { - super(s, e); - } + public ServerException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java index 10d325b..a11ead7 100644 --- a/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/ValidationException.java @@ -22,13 +22,13 @@ public class ValidationException extends Exception { - private static final long serialVersionUID = 974071100448457158L; + private static final long serialVersionUID = 974071100448457158L; - public ValidationException(String s) { - super(s); - } + public ValidationException(String s) { + super(s); + } - public ValidationException(String s, Throwable e) { - super(s, e); - } + public ValidationException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java b/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java index 1f3b17e..8c17c0a 100644 --- a/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java +++ b/src/main/java/net/identio/server/service/orchestration/exceptions/WebSecurityException.java @@ -23,13 +23,13 @@ public class WebSecurityException extends Exception { - private static final long serialVersionUID = -5444195629811859215L; + private static final long serialVersionUID = -5444195629811859215L; - public WebSecurityException(String s) { - super(s); - } + public WebSecurityException(String s) { + super(s); + } - public WebSecurityException(String s, Throwable e) { - super(s, e); - } + public WebSecurityException(String s, Throwable e) { + super(s, e); + } } diff --git a/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java index bfc4fcb..7530d2e 100644 --- a/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java +++ b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java @@ -27,5 +27,5 @@ public class OrchestrationErrorStatus { public static final String AUTH_METHOD_UNKNOWN = "auth.method.unknown"; public static final String AUTH_METHOD_NOT_ALLOWED = "auth.method.not.allowed"; public static final String INVALID_TRANSACTION = "invalid.transaction"; - public static final String INVALID_REQUEST = "invalid.request"; + public static final String INVALID_REQUEST = "invalid.request"; } diff --git a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java index 2bc2d57..d81afd4 100644 --- a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java +++ b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java @@ -28,123 +28,123 @@ public class RequestParsingInfo { - private RequestParsingStatus status; - private String errorStatus; - private String requestId; - private ProtocolType protocolType; - private String sourceApplicationName; - private boolean forceAuthentication; - private String authLevelComparison; - private List requestedAuthLevels; - private String relayState; - private String responseUrl; - private List requestedScopes; - private String responseType; - - public RequestParsingStatus getStatus() { - return status; - } - - public RequestParsingInfo setStatus(RequestParsingStatus status) { - this.status = status; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public RequestParsingInfo setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public String getRequestId() { - return requestId; - } - - public RequestParsingInfo setRequestId(String requestId) { - this.requestId = requestId; - return this; - } - - public ProtocolType getProtocolType() { - return protocolType; - } - - public RequestParsingInfo setProtocolType(ProtocolType protocolType) { - this.protocolType = protocolType; - return this; - } - - public String getSourceApplicationName() { - return sourceApplicationName; - } - - public RequestParsingInfo setSourceApplicationName(String sourceApplicationName) { - this.sourceApplicationName = sourceApplicationName; - return this; - } - - public boolean isForceAuthentication() { - return forceAuthentication; - } - - public RequestParsingInfo setForceAuthentication(boolean forceAuthentication) { - this.forceAuthentication = forceAuthentication; - return this; - } - - public String getAuthLevelComparison() { - return authLevelComparison; - } - - public RequestParsingInfo setAuthLevelComparison(String authLevelComparison) { - this.authLevelComparison = authLevelComparison; - return this; - } - - public List getRequestedAuthLevels() { - return requestedAuthLevels; - } - - public RequestParsingInfo setRequestedAuthLevels(List requestedAuthLevels) { - this.requestedAuthLevels = requestedAuthLevels; - return this; - } - - public String getRelayState() { - return relayState; - } - - public RequestParsingInfo setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getResponseUrl() { - return responseUrl; - } - - public RequestParsingInfo setResponseUrl(String responseUrl) { - this.responseUrl = responseUrl; - return this; - } - - public List getRequestedScopes() { - return requestedScopes; - } - - public RequestParsingInfo setRequestedScopes(List requestedScopes) { - this.requestedScopes = requestedScopes; - return this; - } - - public String getResponseType() { - return responseType; - } - - public void setResponseType(String responseType) { - this.responseType = responseType; - } + private RequestParsingStatus status; + private String errorStatus; + private String requestId; + private ProtocolType protocolType; + private String sourceApplicationName; + private boolean forceAuthentication; + private String authLevelComparison; + private List requestedAuthLevels; + private String relayState; + private String responseUrl; + private List requestedScopes; + private String responseType; + + public RequestParsingStatus getStatus() { + return status; + } + + public RequestParsingInfo setStatus(RequestParsingStatus status) { + this.status = status; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public RequestParsingInfo setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public String getRequestId() { + return requestId; + } + + public RequestParsingInfo setRequestId(String requestId) { + this.requestId = requestId; + return this; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public RequestParsingInfo setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + return this; + } + + public String getSourceApplicationName() { + return sourceApplicationName; + } + + public RequestParsingInfo setSourceApplicationName(String sourceApplicationName) { + this.sourceApplicationName = sourceApplicationName; + return this; + } + + public boolean isForceAuthentication() { + return forceAuthentication; + } + + public RequestParsingInfo setForceAuthentication(boolean forceAuthentication) { + this.forceAuthentication = forceAuthentication; + return this; + } + + public String getAuthLevelComparison() { + return authLevelComparison; + } + + public RequestParsingInfo setAuthLevelComparison(String authLevelComparison) { + this.authLevelComparison = authLevelComparison; + return this; + } + + public List getRequestedAuthLevels() { + return requestedAuthLevels; + } + + public RequestParsingInfo setRequestedAuthLevels(List requestedAuthLevels) { + this.requestedAuthLevels = requestedAuthLevels; + return this; + } + + public String getRelayState() { + return relayState; + } + + public RequestParsingInfo setRelayState(String relayState) { + this.relayState = relayState; + return this; + } + + public String getResponseUrl() { + return responseUrl; + } + + public RequestParsingInfo setResponseUrl(String responseUrl) { + this.responseUrl = responseUrl; + return this; + } + + public List getRequestedScopes() { + return requestedScopes; + } + + public RequestParsingInfo setRequestedScopes(List requestedScopes) { + this.requestedScopes = requestedScopes; + return this; + } + + public String getResponseType() { + return responseType; + } + + public void setResponseType(String responseType) { + this.responseType = responseType; + } } diff --git a/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java b/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java index 58d36ef..0dddb71 100644 --- a/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java +++ b/src/main/java/net/identio/server/service/orchestration/model/SamlAuthRequestGenerationResult.java @@ -24,85 +24,85 @@ public class SamlAuthRequestGenerationResult { - private boolean success; - private String errorStatus; - private Endpoint targetEndpoint; - private String serializedRequest; - private String relayState; - private String signature; - private String signatureAlgorithm; - private String requestId; - - public boolean isSuccess() { - return success; - } - - public SamlAuthRequestGenerationResult setSuccess(boolean success) { - this.success = success; - return this; - } - - public String getErrorStatus() { - return errorStatus; - } - - public SamlAuthRequestGenerationResult setErrorStatus(String errorStatus) { - this.errorStatus = errorStatus; - return this; - } - - public Endpoint getTargetEndpoint() { - return targetEndpoint; - } - - public SamlAuthRequestGenerationResult setTargetEndpoint(Endpoint targetEndpoint) { - this.targetEndpoint = targetEndpoint; - return this; - } - - public String getSerializedRequest() { - return serializedRequest; - } - - public SamlAuthRequestGenerationResult setSerializedRequest(String serializedRequest) { - this.serializedRequest = serializedRequest; - return this; - } - - public String getRelayState() { - return relayState; - } - - public SamlAuthRequestGenerationResult setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getSignature() { - return signature; - } - - public SamlAuthRequestGenerationResult setSignature(String signature) { - this.signature = signature; - return this; - } - - public String getSignatureAlgorithm() { - return signatureAlgorithm; - } - - public SamlAuthRequestGenerationResult setSignatureAlgorithm(String signatureAlgorithm) { - this.signatureAlgorithm = signatureAlgorithm; - return this; - } - - public String getRequestId() { - return requestId; - } - - public SamlAuthRequestGenerationResult setRequestId(String requestId) { - this.requestId = requestId; - return this; - } + private boolean success; + private String errorStatus; + private Endpoint targetEndpoint; + private String serializedRequest; + private String relayState; + private String signature; + private String signatureAlgorithm; + private String requestId; + + public boolean isSuccess() { + return success; + } + + public SamlAuthRequestGenerationResult setSuccess(boolean success) { + this.success = success; + return this; + } + + public String getErrorStatus() { + return errorStatus; + } + + public SamlAuthRequestGenerationResult setErrorStatus(String errorStatus) { + this.errorStatus = errorStatus; + return this; + } + + public Endpoint getTargetEndpoint() { + return targetEndpoint; + } + + public SamlAuthRequestGenerationResult setTargetEndpoint(Endpoint targetEndpoint) { + this.targetEndpoint = targetEndpoint; + return this; + } + + public String getSerializedRequest() { + return serializedRequest; + } + + public SamlAuthRequestGenerationResult setSerializedRequest(String serializedRequest) { + this.serializedRequest = serializedRequest; + return this; + } + + public String getRelayState() { + return relayState; + } + + public SamlAuthRequestGenerationResult setRelayState(String relayState) { + this.relayState = relayState; + return this; + } + + public String getSignature() { + return signature; + } + + public SamlAuthRequestGenerationResult setSignature(String signature) { + this.signature = signature; + return this; + } + + public String getSignatureAlgorithm() { + return signatureAlgorithm; + } + + public SamlAuthRequestGenerationResult setSignatureAlgorithm(String signatureAlgorithm) { + this.signatureAlgorithm = signatureAlgorithm; + return this; + } + + public String getRequestId() { + return requestId; + } + + public SamlAuthRequestGenerationResult setRequestId(String requestId) { + this.requestId = requestId; + return this; + } } diff --git a/src/main/java/net/identio/server/service/saml/MetadataService.java b/src/main/java/net/identio/server/service/saml/MetadataService.java index f91b2e9..a2f1a9b 100644 --- a/src/main/java/net/identio/server/service/saml/MetadataService.java +++ b/src/main/java/net/identio/server/service/saml/MetadataService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.saml; diff --git a/src/main/java/net/identio/server/service/saml/SamlService.java b/src/main/java/net/identio/server/service/saml/SamlService.java index f9b809e..da22422 100644 --- a/src/main/java/net/identio/server/service/saml/SamlService.java +++ b/src/main/java/net/identio/server/service/saml/SamlService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.saml; @@ -51,437 +52,438 @@ License, or (at your option) any later version. @Scope("singleton") public class SamlService { - private static final Logger LOG = LoggerFactory.getLogger(SamlService.class); + private static final Logger LOG = LoggerFactory.getLogger(SamlService.class); + + private Signer signer; + + private MetadataService metadataService; + + private ConfigurationService configurationService; + + private AuthPolicyService authPolicyService; - private Signer signer; + @Autowired + public SamlService(ConfigurationService configurationService, MetadataService metadataService, + AuthPolicyService authPolicyService) throws InitializationException { - private MetadataService metadataService; + this.configurationService = configurationService; + this.metadataService = metadataService; + this.authPolicyService = authPolicyService; - private ConfigurationService configurationService; - - private AuthPolicyService authPolicyService; + try { + + initSigner(configurationService.getConfiguration()); + } catch (TechnicalException ex) { + String message = "Could not initialize SamlService"; + LOG.error("{}: {}", message, ex.getMessage()); + throw new InitializationException(message, ex); + } + } - @Autowired - public SamlService(ConfigurationService configurationService, MetadataService metadataService, - AuthPolicyService authPolicyService) throws InitializationException { - - this.configurationService = configurationService; - this.metadataService = metadataService; - this.authPolicyService = authPolicyService; - - try { - - initSigner(configurationService.getConfiguration()); - } catch (TechnicalException ex) { - String message = "Could not initialize SamlService"; - LOG.error("{}: {}", message, ex.getMessage()); - throw new InitializationException(message, ex); - } - } - - private void initSigner(IdentioConfiguration config) throws TechnicalException { + private void initSigner(IdentioConfiguration config) throws TechnicalException { - String keystoreFile = config.getGlobalConfiguration().getSignatureKeystorePath(); - String keystorePassword = config.getGlobalConfiguration().getSignatureKeystorePassword(); - boolean isCertificateCheckEnabled = config.getSamlIdpConfiguration().isCertificateCheckEnabled(); - - LOG.debug("Initializing SAML signer..."); - - signer = new Signer(keystoreFile, keystorePassword, isCertificateCheckEnabled, - SamlConstants.SIGNATURE_ALG_RSA_SHA256); - } - - public RequestParsingInfo validateAuthentRequest(SamlInboundRequest request) { - - LOG.debug("Starting SAML Authentication Request orchestration..."); - - RequestParsingInfo result = new RequestParsingInfo(); - - result.setProtocolType(ProtocolType.SAML); - - // Parse the authentication request - AuthentRequest ar; - try { - ar = AuthentRequestBuilder.getInstance().build(request.getSerializedRequest(), false); - } catch (TechnicalException | InvalidRequestException e1) { - LOG.error("Impossible to build AuthentRequest"); - return result.setStatus(RequestParsingStatus.FATAL_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); - } - - // Extract interesting values - String requestIssuer = ar.getIssuer(); - - ArrayList requestedAuthnContext = ar.getRequestedAuthnContext(); - String comparison = ar.getAuthnContextComparison(); - boolean forceAuthn = ar.isForceAuthn(); - String requestId = ar.getId(); - Endpoint destinationEndpoint = findResponseEndpoint(ar); - - if (destinationEndpoint == null) { - LOG.error("No suitable response endpoint found"); - return result.setStatus(RequestParsingStatus.FATAL_ERROR) - .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); - } - - result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) - .setForceAuthentication(forceAuthn).setProtocolType(ProtocolType.SAML) - .setRelayState(request.getRelayState()).setResponseUrl(destinationEndpoint.getLocation()); - - // Extract the requested authentication level, if any - if (requestedAuthnContext != null) { - ArrayList requestedAuthLevels = new ArrayList<>(); - - for (String authLevelString : requestedAuthnContext) { - try { - requestedAuthLevels.add(authPolicyService.getAuthLevelByUrn(authLevelString)); - } catch (UnknownAuthLevelException e) { - return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_NO_AUTHN_CONTEXT); - } - } - - result.setRequestedAuthLevels(requestedAuthLevels); - } - - LOG.debug("* Request Issuer: {} ", requestIssuer); - LOG.debug("* Request ID: {}", requestId); - if (LOG.isDebugEnabled() && requestedAuthnContext != null) { - for (String s : requestedAuthnContext) { - LOG.debug("* Requested authentication context : {}", s); - } - } - LOG.debug("* Comparison: {}", comparison); - LOG.debug("* Request forcing reauthentication: {}", forceAuthn); - - // The request issuer field cannot be null - if (requestIssuer == null) { - LOG.error("Request Issuer is empty"); - return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - } - - // Check if the issuer is registered - Validator validator = metadataService.getSpValidator(requestIssuer); - if (validator == null) { - LOG.error("No validator found for issuer {}", requestIssuer); - return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - } - - // Check that we are the recipient of the Authentication Request - String destination = ar.getDestination(); - - if (destination == null) { - LOG.error("No destination specified in request"); - return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); - - } else { - - boolean endpointFound = false; - - for (IdpSsoDescriptor descriptor : metadataService.getIdpMetadata().getIdpSsoDescriptors()) { - for (Endpoint endpoint : descriptor.getSsoEndpoints()) { - if (endpoint.getLocation().equals(destination) - && request.getBinding().equals(endpoint.getBinding())) { - endpointFound = true; - } - } - } - if (!endpointFound) { - LOG.error("The request destination doesn't match server SAML endpoints"); - return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); - } - } - - // Check the signature and the conditions - if (SamlConstants.BINDING_HTTP_REDIRECT.equals(request.getBinding()) - && !validateRedirectRequest(validator, request, result) - || !validatePostRequest(validator, ar, result)) { - return result; - } - - LOG.debug("* Request is valid"); - result.setStatus(RequestParsingStatus.OK); - - return result; - - } - - private boolean validateRedirectRequest(Validator validator, SamlInboundRequest request, - RequestParsingInfo result) { - - LOG.debug("Validate query parameters of HTTP-Redirect Binding"); - - byte[] signature; - try { - signature = DecodeUtils.decode(request.getSignatureValue(), false); - } catch (Base64DecodingException | IOException | DataFormatException e) { - result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); - return false; - } - String signedInfo = request.getSignedInfo(); - String sigAlg = request.getSignatureAlgorithm(); - - if (signature != null && signedInfo != null && sigAlg != null) { - - LOG.debug("* Request is signed"); - - try { - validator.validate(signedInfo, signature, sigAlg); - } catch (NoSuchAlgorithmException | TechnicalException | InvalidSignatureException e) { - LOG.error("Request signature is invalid"); - result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - return false; - } - - LOG.debug("* Request signature is valid"); - - } else { - - LOG.debug("* Request is not signed"); - - if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { - LOG.error("Unsigned requests are not supported."); - result.setStatus(RequestParsingStatus.RESPONSE_ERROR) - .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - return false; - } - } - - return true; - } - - private boolean validatePostRequest(Validator validator, AuthentRequest ar, RequestParsingInfo result) { - - LOG.debug("Validate query parameters of HTTP-POST Binding"); - - if (ar.isSigned()) { - - LOG.debug("* Request is signed"); + String keystoreFile = config.getGlobalConfiguration().getSignatureKeystorePath(); + String keystorePassword = config.getGlobalConfiguration().getSignatureKeystorePassword(); + boolean isCertificateCheckEnabled = config.getSamlIdpConfiguration().isCertificateCheckEnabled(); - try { - validator.validate(ar); - } catch (NoSuchAlgorithmException | UnsignedSAMLObjectException | TechnicalException - | UntrustedSignerException | InvalidSignatureException e) { - LOG.error("Request signature is invalid"); - result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - return false; - } + LOG.debug("Initializing SAML signer..."); + + signer = new Signer(keystoreFile, keystorePassword, isCertificateCheckEnabled, + SamlConstants.SIGNATURE_ALG_RSA_SHA256); + } + + public RequestParsingInfo validateAuthentRequest(SamlInboundRequest request) { + + LOG.debug("Starting SAML Authentication Request orchestration..."); + + RequestParsingInfo result = new RequestParsingInfo(); + + result.setProtocolType(ProtocolType.SAML); + + // Parse the authentication request + AuthentRequest ar; + try { + ar = AuthentRequestBuilder.getInstance().build(request.getSerializedRequest(), false); + } catch (TechnicalException | InvalidRequestException e1) { + LOG.error("Impossible to build AuthentRequest"); + return result.setStatus(RequestParsingStatus.FATAL_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); + } + + // Extract interesting values + String requestIssuer = ar.getIssuer(); + + ArrayList requestedAuthnContext = ar.getRequestedAuthnContext(); + String comparison = ar.getAuthnContextComparison(); + boolean forceAuthn = ar.isForceAuthn(); + String requestId = ar.getId(); + Endpoint destinationEndpoint = findResponseEndpoint(ar); + + if (destinationEndpoint == null) { + LOG.error("No suitable response endpoint found"); + return result.setStatus(RequestParsingStatus.FATAL_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + } + + result.setRequestId(requestId).setSourceApplicationName(requestIssuer).setAuthLevelComparison(comparison) + .setForceAuthentication(forceAuthn).setProtocolType(ProtocolType.SAML) + .setRelayState(request.getRelayState()).setResponseUrl(destinationEndpoint.getLocation()); + + // Extract the requested authentication level, if any + if (requestedAuthnContext != null) { + ArrayList requestedAuthLevels = new ArrayList<>(); + + for (String authLevelString : requestedAuthnContext) { + try { + requestedAuthLevels.add(authPolicyService.getAuthLevelByUrn(authLevelString)); + } catch (UnknownAuthLevelException e) { + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_NO_AUTHN_CONTEXT); + } + } + + result.setRequestedAuthLevels(requestedAuthLevels); + } + + LOG.debug("* Request Issuer: {} ", requestIssuer); + LOG.debug("* Request ID: {}", requestId); + if (LOG.isDebugEnabled() && requestedAuthnContext != null) { + for (String s : requestedAuthnContext) { + LOG.debug("* Requested authentication context : {}", s); + } + } + LOG.debug("* Comparison: {}", comparison); + LOG.debug("* Request forcing reauthentication: {}", forceAuthn); + + // The request issuer field cannot be null + if (requestIssuer == null) { + LOG.error("Request Issuer is empty"); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + } + + // Check if the issuer is registered + Validator validator = metadataService.getSpValidator(requestIssuer); + if (validator == null) { + LOG.error("No validator found for issuer {}", requestIssuer); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + } + + // Check that we are the recipient of the Authentication Request + String destination = ar.getDestination(); + + if (destination == null) { + LOG.error("No destination specified in request"); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + + } else { + + boolean endpointFound = false; + + for (IdpSsoDescriptor descriptor : metadataService.getIdpMetadata().getIdpSsoDescriptors()) { + for (Endpoint endpoint : descriptor.getSsoEndpoints()) { + if (endpoint.getLocation().equals(destination) + && request.getBinding().equals(endpoint.getBinding())) { + endpointFound = true; + } + } + } + if (!endpointFound) { + LOG.error("The request destination doesn't match server SAML endpoints"); + return result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_UNSUPPORTED_BINDING); + } + } + + // Check the signature and the conditions + if (SamlConstants.BINDING_HTTP_REDIRECT.equals(request.getBinding()) + && !validateRedirectRequest(validator, request, result) + || !validatePostRequest(validator, ar, result)) { + return result; + } + + LOG.debug("* Request is valid"); + result.setStatus(RequestParsingStatus.OK); + + return result; + + } + + private boolean validateRedirectRequest(Validator validator, SamlInboundRequest request, + RequestParsingInfo result) { + + LOG.debug("Validate query parameters of HTTP-Redirect Binding"); + + byte[] signature; + try { + signature = DecodeUtils.decode(request.getSignatureValue(), false); + } catch (Base64DecodingException | IOException | DataFormatException e) { + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_UNSUPPORTED); + return false; + } + String signedInfo = request.getSignedInfo(); + String sigAlg = request.getSignatureAlgorithm(); + + if (signature != null && signedInfo != null && sigAlg != null) { + + LOG.debug("* Request is signed"); + + try { + validator.validate(signedInfo, signature, sigAlg); + } catch (NoSuchAlgorithmException | TechnicalException | InvalidSignatureException e) { + LOG.error("Request signature is invalid"); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return false; + } + + LOG.debug("* Request signature is valid"); + + } else { + + LOG.debug("* Request is not signed"); + + if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { + LOG.error("Unsigned requests are not supported."); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR) + .setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return false; + } + } + + return true; + } + + private boolean validatePostRequest(Validator validator, AuthentRequest ar, RequestParsingInfo result) { + + LOG.debug("Validate query parameters of HTTP-POST Binding"); + + if (ar.isSigned()) { + + LOG.debug("* Request is signed"); - LOG.debug("* Request signature is valid"); + try { + validator.validate(ar); + } catch (NoSuchAlgorithmException | UnsignedSAMLObjectException | TechnicalException + | UntrustedSignerException | InvalidSignatureException e) { + LOG.error("Request signature is invalid"); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return false; + } - } else { - LOG.debug("* Request is not signed"); + LOG.debug("* Request signature is valid"); - if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { - LOG.error("Unsigned requests are not supported."); - result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); - return false; - } + } else { + LOG.debug("* Request is not signed"); - } + if (!configurationService.getConfiguration().getSamlIdpConfiguration().isAllowUnsecureRequests()) { + LOG.error("Unsigned requests are not supported."); + result.setStatus(RequestParsingStatus.RESPONSE_ERROR).setErrorStatus(SamlConstants.STATUS_REQUEST_DENIED); + return false; + } - return true; - } + } - public ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo requestParsingInfo, - UserSession userSession) throws SamlException { + return true; + } - LOG.debug("Generating a new SAML Response"); + public ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo requestParsingInfo, + UserSession userSession) throws SamlException { - String spEntityID = requestParsingInfo.getSourceApplicationName(); - String requestID = requestParsingInfo.getRequestId(); - String userId = userSession.getUserId(); - AuthSession authSession = decision.getValidatedAuthSession(); - String authnLevel = authSession.getAuthLevel().getUrn(); - DateTime authnInstant = authSession.getAuthInstant(); - String sessionId = userSession.getId(); - String destinationUrl = requestParsingInfo.getResponseUrl(); + LOG.debug("Generating a new SAML Response"); - // Determine the assertion consumer endpoint + String spEntityID = requestParsingInfo.getSourceApplicationName(); + String requestID = requestParsingInfo.getRequestId(); + String userId = userSession.getUserId(); + AuthSession authSession = decision.getValidatedAuthSession(); + String authnLevel = authSession.getAuthLevel().getUrn(); + DateTime authnInstant = authSession.getAuthInstant(); + String sessionId = userSession.getId(); + String destinationUrl = requestParsingInfo.getResponseUrl(); - LOG.debug("* Entity ID: {}", spEntityID); - LOG.debug("* User ID: {}", userId); - LOG.debug("* In response to request: {}", requestID); - LOG.debug("* AuthLevel: {}", authnLevel); - LOG.debug("* Authentication time: {}", authnInstant.toString()); - - // Build the assertion - try { - Assertion assertion = AssertionBuilder.getInstance() - .setIssuer(metadataService.getIdpMetadata().getEntityID()) - .setSubject(userId, SamlConstants.NAMEID_UNSPECIFIED) - .setSubjectConfirmation(SamlConstants.SUBJECT_CONFIRMATION_BEARER, requestID, destinationUrl) - .setConditions(spEntityID, - configurationService.getConfiguration().getSamlIdpConfiguration().getTokenValidityLength(), - configurationService.getConfiguration().getSamlIdpConfiguration().getAllowedTimeOffset()) - .setAuthentStatement(authnLevel, authnInstant, sessionId).build(); - - LOG.debug("* SAML Assertion built"); - - // Build the response - AuthentResponse response = AuthentResponseBuilder.getInstance() - .setIssuer(metadataService.getIdpMetadata().getEntityID()).setStatus(true, null) - .setDestination(destinationUrl).setAssertion(assertion).build(); - - LOG.debug("* SAML response built"); - - // Sign the response - signer.signEmbedded(response); - - LOG.debug("* SAML response signed"); - - String data = DecodeUtils.encode(response.toString().getBytes(), false); - - return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) - .setData(data) - .setRelayState(requestParsingInfo.getRelayState()); - - } catch (TechnicalException | IOException ex) { - String message = "Technical error when building SAML response"; - LOG.error("{}: {}", message, ex.getMessage()); - throw new SamlException(message, ex); - } - } - - public ResponseData generateErrorResponse(RequestParsingInfo requestParsingInfo) throws SamlException { + // Determine the assertion consumer endpoint - LOG.debug("Generating a new SAML Error Response"); + LOG.debug("* Entity ID: {}", spEntityID); + LOG.debug("* User ID: {}", userId); + LOG.debug("* In response to request: {}", requestID); + LOG.debug("* AuthLevel: {}", authnLevel); + LOG.debug("* Authentication time: {}", authnInstant.toString()); + + // Build the assertion + try { + Assertion assertion = AssertionBuilder.getInstance() + .setIssuer(metadataService.getIdpMetadata().getEntityID()) + .setSubject(userId, SamlConstants.NAMEID_UNSPECIFIED) + .setSubjectConfirmation(SamlConstants.SUBJECT_CONFIRMATION_BEARER, requestID, destinationUrl) + .setConditions(spEntityID, + configurationService.getConfiguration().getSamlIdpConfiguration().getTokenValidityLength(), + configurationService.getConfiguration().getSamlIdpConfiguration().getAllowedTimeOffset()) + .setAuthentStatement(authnLevel, authnInstant, sessionId).build(); + + LOG.debug("* SAML Assertion built"); + + // Build the response + AuthentResponse response = AuthentResponseBuilder.getInstance() + .setIssuer(metadataService.getIdpMetadata().getEntityID()).setStatus(true, null) + .setDestination(destinationUrl).setAssertion(assertion).build(); + + LOG.debug("* SAML response built"); + + // Sign the response + signer.signEmbedded(response); + + LOG.debug("* SAML response signed"); + + String data = DecodeUtils.encode(response.toString().getBytes(), false); + + return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) + .setData(data) + .setRelayState(requestParsingInfo.getRelayState()); + + } catch (TechnicalException | IOException ex) { + String message = "Technical error when building SAML response"; + LOG.error("{}: {}", message, ex.getMessage()); + throw new SamlException(message, ex); + } + } + + public ResponseData generateErrorResponse(RequestParsingInfo requestParsingInfo) throws SamlException { + + LOG.debug("Generating a new SAML Error Response"); - String destinationUrl = requestParsingInfo.getResponseUrl(); - - if (destinationUrl == null) { - String message = "* Destination URL cannot be null"; - LOG.error(message); - throw new SamlException(message); - } - - // Build the response - try { - - // Build the response - AuthentResponse response = AuthentResponseBuilder.getInstance() - .setIssuer(metadataService.getIdpMetadata().getEntityID()) - .setStatus(false, requestParsingInfo.getErrorStatus()).setDestination(destinationUrl).build(); - - LOG.debug("* SAML response built"); - - String data = DecodeUtils.encode(response.toString().getBytes(), false); - - return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) - .setData(data) - .setRelayState(requestParsingInfo.getRelayState()); - - } catch (TechnicalException | IOException ex) { - String message = "Technical error when building SAML response"; - LOG.error("{}: {}", message, ex.getMessage()); - throw new SamlException(message, ex); - } - } - - private Endpoint findResponseEndpoint(AuthentRequest ar) { - Endpoint selectedEndpoint = null; - - outerloop: for (SpSsoDescriptor descriptor : metadataService.getSpMetadata(ar.getIssuer()) - .getSpSsoDescriptors()) { - for (Endpoint endpoint : descriptor.getAssertionConsumerServices()) { - - // Preference to the location specified in the request - if (ar.getPreferredEndPoint() != null) { - if (ar.getPreferEndpointIndex() - && ar.getPreferredEndPoint().getIndex().equals(endpoint.getIndex())) { - selectedEndpoint = endpoint; - break outerloop; - } - if (!ar.getPreferEndpointIndex() - && ar.getPreferredEndPoint().getLocation().equals(endpoint.getLocation()) - && ar.getPreferredEndPoint().getBinding().equals(endpoint.getBinding())) { - selectedEndpoint = endpoint; - break outerloop; - } - } else { - if (endpoint.isDefault()) { - selectedEndpoint = endpoint; - } - } - } - } - - return selectedEndpoint; - } - - private Endpoint findRequestEndpoint(Metadata remoteIdpMetadata) { - Endpoint selectedEndpoint = null; - - // Find IDP endoint - for (Endpoint endpoint : remoteIdpMetadata.getIdpSsoDescriptors().get(0).getSsoEndpoints()) { - if (selectedEndpoint == null) { - selectedEndpoint = endpoint; - } else { - if (endpoint.isDefault()) { - selectedEndpoint = endpoint; - } - } - } - - return selectedEndpoint; - } - - public SamlAuthRequestGenerationResult generateAuthentRequest(Metadata remoteIdpMetadata, - ArrayList requestedAuthnContext, String comparison, String transactionId) throws SamlException { - - LOG.debug("Generating a new SAML Request"); - - SamlAuthRequestGenerationResult result = new SamlAuthRequestGenerationResult(); - - try { - Metadata idpMetadata = metadataService.getIdpMetadata(); - - Endpoint remoteEndpoint = findRequestEndpoint(remoteIdpMetadata); - result.setTargetEndpoint(remoteEndpoint); - - AuthentRequest authentRequest = AuthentRequestBuilder.getInstance().setIssuer(idpMetadata.getEntityID()) - .setDestination(remoteEndpoint.getLocation()).setForceAuthent(false).setIsPassive(false) - .setRequestedAuthnContext(requestedAuthnContext, comparison).build(); - - result.setRequestId(authentRequest.getId()); - - if (remoteEndpoint.getBinding().equals(SamlConstants.BINDING_HTTP_POST)) { - signer.signEmbedded(authentRequest); - result.setSerializedRequest(DecodeUtils.encode(authentRequest.toString().getBytes(), false)) - .setRelayState(transactionId); - } else { - // Generate the information to sign - String encodedSamlRequest = UriUtils - .encode(DecodeUtils.encode(authentRequest.toString().getBytes(), true), "UTF-8"); - String encodedRelayState = UriUtils.encode(transactionId, "UTF-8"); - String encodedSigAlg = UriUtils.encode(SamlConstants.SIGNATURE_ALG_RSA_SHA256, "UTF-8"); - - String signedInfo = "SAMLRequest=" + encodedSamlRequest + "&RelayState=" + encodedRelayState - + "&SigAlg=" + encodedSigAlg; - String encodedSignature = UriUtils.encode(DecodeUtils.encode(signer.signExternal(signedInfo), false), - "UTF-8"); - - result.setSignature(encodedSignature).setSerializedRequest(encodedSamlRequest) - .setRelayState(encodedRelayState).setSignatureAlgorithm(encodedSigAlg); - } - - LOG.debug("* SAML request built"); - result.setSuccess(true); - - return result; - - } catch (TechnicalException | IOException ex) { - String message = "Technical error when building SAML request"; - LOG.error("{}: {}", message, ex.getMessage()); - throw new SamlException(message, ex); - } - - } + String destinationUrl = requestParsingInfo.getResponseUrl(); + + if (destinationUrl == null) { + String message = "* Destination URL cannot be null"; + LOG.error(message); + throw new SamlException(message); + } + + // Build the response + try { + + // Build the response + AuthentResponse response = AuthentResponseBuilder.getInstance() + .setIssuer(metadataService.getIdpMetadata().getEntityID()) + .setStatus(false, requestParsingInfo.getErrorStatus()).setDestination(destinationUrl).build(); + + LOG.debug("* SAML response built"); + + String data = DecodeUtils.encode(response.toString().getBytes(), false); + + return new ResponseData().setUrl(requestParsingInfo.getResponseUrl()) + .setData(data) + .setRelayState(requestParsingInfo.getRelayState()); + + } catch (TechnicalException | IOException ex) { + String message = "Technical error when building SAML response"; + LOG.error("{}: {}", message, ex.getMessage()); + throw new SamlException(message, ex); + } + } + + private Endpoint findResponseEndpoint(AuthentRequest ar) { + Endpoint selectedEndpoint = null; + + outerloop: + for (SpSsoDescriptor descriptor : metadataService.getSpMetadata(ar.getIssuer()) + .getSpSsoDescriptors()) { + for (Endpoint endpoint : descriptor.getAssertionConsumerServices()) { + + // Preference to the location specified in the request + if (ar.getPreferredEndPoint() != null) { + if (ar.getPreferEndpointIndex() + && ar.getPreferredEndPoint().getIndex().equals(endpoint.getIndex())) { + selectedEndpoint = endpoint; + break outerloop; + } + if (!ar.getPreferEndpointIndex() + && ar.getPreferredEndPoint().getLocation().equals(endpoint.getLocation()) + && ar.getPreferredEndPoint().getBinding().equals(endpoint.getBinding())) { + selectedEndpoint = endpoint; + break outerloop; + } + } else { + if (endpoint.isDefault()) { + selectedEndpoint = endpoint; + } + } + } + } + + return selectedEndpoint; + } + + private Endpoint findRequestEndpoint(Metadata remoteIdpMetadata) { + Endpoint selectedEndpoint = null; + + // Find IDP endoint + for (Endpoint endpoint : remoteIdpMetadata.getIdpSsoDescriptors().get(0).getSsoEndpoints()) { + if (selectedEndpoint == null) { + selectedEndpoint = endpoint; + } else { + if (endpoint.isDefault()) { + selectedEndpoint = endpoint; + } + } + } + + return selectedEndpoint; + } + + public SamlAuthRequestGenerationResult generateAuthentRequest(Metadata remoteIdpMetadata, + ArrayList requestedAuthnContext, String comparison, String transactionId) throws SamlException { + + LOG.debug("Generating a new SAML Request"); + + SamlAuthRequestGenerationResult result = new SamlAuthRequestGenerationResult(); + + try { + Metadata idpMetadata = metadataService.getIdpMetadata(); + + Endpoint remoteEndpoint = findRequestEndpoint(remoteIdpMetadata); + result.setTargetEndpoint(remoteEndpoint); + + AuthentRequest authentRequest = AuthentRequestBuilder.getInstance().setIssuer(idpMetadata.getEntityID()) + .setDestination(remoteEndpoint.getLocation()).setForceAuthent(false).setIsPassive(false) + .setRequestedAuthnContext(requestedAuthnContext, comparison).build(); + + result.setRequestId(authentRequest.getId()); + + if (remoteEndpoint.getBinding().equals(SamlConstants.BINDING_HTTP_POST)) { + signer.signEmbedded(authentRequest); + result.setSerializedRequest(DecodeUtils.encode(authentRequest.toString().getBytes(), false)) + .setRelayState(transactionId); + } else { + // Generate the information to sign + String encodedSamlRequest = UriUtils + .encode(DecodeUtils.encode(authentRequest.toString().getBytes(), true), "UTF-8"); + String encodedRelayState = UriUtils.encode(transactionId, "UTF-8"); + String encodedSigAlg = UriUtils.encode(SamlConstants.SIGNATURE_ALG_RSA_SHA256, "UTF-8"); + + String signedInfo = "SAMLRequest=" + encodedSamlRequest + "&RelayState=" + encodedRelayState + + "&SigAlg=" + encodedSigAlg; + String encodedSignature = UriUtils.encode(DecodeUtils.encode(signer.signExternal(signedInfo), false), + "UTF-8"); + + result.setSignature(encodedSignature).setSerializedRequest(encodedSamlRequest) + .setRelayState(encodedRelayState).setSignatureAlgorithm(encodedSigAlg); + } + + LOG.debug("* SAML request built"); + result.setSuccess(true); + + return result; + + } catch (TechnicalException | IOException ex) { + String message = "Technical error when building SAML request"; + LOG.error("{}: {}", message, ex.getMessage()); + throw new SamlException(message, ex); + } + + } } diff --git a/src/main/java/net/identio/server/service/transaction/TransactionService.java b/src/main/java/net/identio/server/service/transaction/TransactionService.java index 8e6a90d..131208c 100644 --- a/src/main/java/net/identio/server/service/transaction/TransactionService.java +++ b/src/main/java/net/identio/server/service/transaction/TransactionService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.transaction; @@ -37,79 +38,79 @@ License, or (at your option) any later version. @Scope("singleton") public class TransactionService { - private static final Logger LOG = LoggerFactory.getLogger(TransactionService.class); + private static final Logger LOG = LoggerFactory.getLogger(TransactionService.class); - private LoadingCache transactionCache; + private LoadingCache transactionCache; - public TransactionService() { + public TransactionService() { - transactionCache = CacheBuilder.newBuilder().maximumSize(100000).expireAfterAccess(10, TimeUnit.MINUTES) - .build(new CacheLoader() { - public TransactionData load(String o) { - return new TransactionData(); - } - }); - } + transactionCache = CacheBuilder.newBuilder().maximumSize(100000).expireAfterAccess(10, TimeUnit.MINUTES) + .build(new CacheLoader() { + public TransactionData load(String o) { + return new TransactionData(); + } + }); + } - public TransactionData createTransaction() { + public TransactionData createTransaction() { - LOG.debug("Generating new transaction datas"); + LOG.debug("Generating new transaction datas"); - String transactionId = UUID.randomUUID().toString(); + String transactionId = UUID.randomUUID().toString(); - TransactionData data = new TransactionData(); - data.setTransactionId(transactionId); - transactionCache.put(transactionId, data); + TransactionData data = new TransactionData(); + data.setTransactionId(transactionId); + transactionCache.put(transactionId, data); - LOG.debug("New transaction generated {}", transactionId); + LOG.debug("New transaction generated {}", transactionId); - return data; - } + return data; + } - public void removeTransactionData(TransactionData transactionData) { + public void removeTransactionData(TransactionData transactionData) { - LOG.debug("Destroyed transaction {}", transactionData.getTransactionId()); - transactionCache.invalidate(transactionData.getTransactionId()); - } + LOG.debug("Destroyed transaction {}", transactionData.getTransactionId()); + transactionCache.invalidate(transactionData.getTransactionId()); + } - public TransactionData fetchTransaction(String transactionId) { + public TransactionData fetchTransaction(String transactionId) { - if (transactionId == null) { - return new TransactionData(); - } + if (transactionId == null) { + return new TransactionData(); + } - LOG.debug("Fetch transaction {} in cache", transactionId); + LOG.debug("Fetch transaction {} in cache", transactionId); - try { - return transactionCache.get(transactionId); - } catch (ExecutionException e) { - return new TransactionData(); - } - } + try { + return transactionCache.get(transactionId); + } catch (ExecutionException e) { + return new TransactionData(); + } + } - public TransactionData getTransaction(String sessionId, String transactionId) throws WebSecurityException { + public TransactionData getTransaction(String sessionId, String transactionId) throws WebSecurityException { - LOG.debug("Security verification of coherence between transaction ID and session ID"); + LOG.debug("Security verification of coherence between transaction ID and session ID"); - TransactionData transactionData = fetchTransaction(transactionId); + TransactionData transactionData = fetchTransaction(transactionId); - if (transactionData.getTransactionId() == null) { - String message = "Could not find a valid transaction"; - LOG.error(message); - throw new WebSecurityException(message); - } + if (transactionData.getTransactionId() == null) { + String message = "Could not find a valid transaction"; + LOG.error(message); + throw new WebSecurityException(message); + } - if (!sessionId.equals(transactionData.getUserSession().getId())) { - removeTransactionData(transactionData); + if (!sessionId.equals(transactionData.getUserSession().getId())) { + removeTransactionData(transactionData); - String message = "Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"; - LOG.error(message); - throw new WebSecurityException(message); - } + String message = "Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"; + LOG.error(message); + throw new WebSecurityException(message); + } - LOG.debug("Security verification OK"); + LOG.debug("Security verification OK"); - return transactionData; - } + return transactionData; + } } diff --git a/src/main/java/net/identio/server/service/transaction/model/TransactionData.java b/src/main/java/net/identio/server/service/transaction/model/TransactionData.java index 72de9a0..9a529c9 100644 --- a/src/main/java/net/identio/server/service/transaction/model/TransactionData.java +++ b/src/main/java/net/identio/server/service/transaction/model/TransactionData.java @@ -28,85 +28,85 @@ public class TransactionData { - private String transactionId; - private UserSession userSession; - private RequestParsingInfo requestParsingInfo; - private ArrayList targetAuthLevels; - private HashSet targetAuthMethods = new HashSet<>(); - private AuthMethod selectedAuthMethod; - private TransactionState transactionState; - private String samlProxyRequestId; - private ProtocolType protocolType; - - public String getTransactionId() { - return transactionId; - } - - public void setTransactionId(String transactionId) { - this.transactionId = transactionId; - } - - public UserSession getUserSession() { - return userSession; - } - - public void setUserSession(UserSession userSession) { - this.userSession = userSession; - } - - public RequestParsingInfo getRequestParsingInfo() { - return requestParsingInfo; - } - - public void setRequestParsingInfo(RequestParsingInfo requestParsingInfo) { - this.requestParsingInfo = requestParsingInfo; - } - - public ArrayList getTargetAuthLevels() { - return targetAuthLevels; - } - - public void setTargetAuthLevels(ArrayList targetAuthLevels) { - this.targetAuthLevels = targetAuthLevels; - } - - public HashSet getTargetAuthMethods() { - return targetAuthMethods; - } - - public void setTargetAuthMethods(HashSet targetAuthMethods) { - this.targetAuthMethods = targetAuthMethods; - } - - public AuthMethod getSelectedAuthMethod() { - return selectedAuthMethod; - } - - public void setSelectedAuthMethod(AuthMethod selectedAuthMethod) { - this.selectedAuthMethod = selectedAuthMethod; - } - - public TransactionState getState() { - return transactionState; - } - - public void setState(TransactionState transactionState) { - this.transactionState = transactionState; - } - - public String getSamlProxyRequestId() { - return samlProxyRequestId; - } - - public void setSamlProxyRequestId(String samlProxyRequestId) { - this.samlProxyRequestId = samlProxyRequestId; - } - - public ProtocolType getProtocolType() { - return protocolType; - } - - public void setProtocolType(ProtocolType protocolType) { - this.protocolType = protocolType; - } + private String transactionId; + private UserSession userSession; + private RequestParsingInfo requestParsingInfo; + private ArrayList targetAuthLevels; + private HashSet targetAuthMethods = new HashSet<>(); + private AuthMethod selectedAuthMethod; + private TransactionState transactionState; + private String samlProxyRequestId; + private ProtocolType protocolType; + + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + + public UserSession getUserSession() { + return userSession; + } + + public void setUserSession(UserSession userSession) { + this.userSession = userSession; + } + + public RequestParsingInfo getRequestParsingInfo() { + return requestParsingInfo; + } + + public void setRequestParsingInfo(RequestParsingInfo requestParsingInfo) { + this.requestParsingInfo = requestParsingInfo; + } + + public ArrayList getTargetAuthLevels() { + return targetAuthLevels; + } + + public void setTargetAuthLevels(ArrayList targetAuthLevels) { + this.targetAuthLevels = targetAuthLevels; + } + + public HashSet getTargetAuthMethods() { + return targetAuthMethods; + } + + public void setTargetAuthMethods(HashSet targetAuthMethods) { + this.targetAuthMethods = targetAuthMethods; + } + + public AuthMethod getSelectedAuthMethod() { + return selectedAuthMethod; + } + + public void setSelectedAuthMethod(AuthMethod selectedAuthMethod) { + this.selectedAuthMethod = selectedAuthMethod; + } + + public TransactionState getState() { + return transactionState; + } + + public void setState(TransactionState transactionState) { + this.transactionState = transactionState; + } + + public String getSamlProxyRequestId() { + return samlProxyRequestId; + } + + public void setSamlProxyRequestId(String samlProxyRequestId) { + this.samlProxyRequestId = samlProxyRequestId; + } + + public ProtocolType getProtocolType() { + return protocolType; + } + + public void setProtocolType(ProtocolType protocolType) { + this.protocolType = protocolType; + } } diff --git a/src/main/java/net/identio/server/service/userdetails/UserDetailsService.java b/src/main/java/net/identio/server/service/userdetails/UserDetailsService.java index 396aca0..228ff10 100644 --- a/src/main/java/net/identio/server/service/userdetails/UserDetailsService.java +++ b/src/main/java/net/identio/server/service/userdetails/UserDetailsService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.userdetails; diff --git a/src/main/java/net/identio/server/service/usersession/UserSessionService.java b/src/main/java/net/identio/server/service/usersession/UserSessionService.java index 71aa4a3..80fbc1e 100644 --- a/src/main/java/net/identio/server/service/usersession/UserSessionService.java +++ b/src/main/java/net/identio/server/service/usersession/UserSessionService.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.service.usersession; @@ -38,73 +39,73 @@ License, or (at your option) any later version. @Scope("singleton") public class UserSessionService { - private static final Logger LOG = LoggerFactory.getLogger(UserSessionService.class); + private static final Logger LOG = LoggerFactory.getLogger(UserSessionService.class); - private LoadingCache sessionCache; + private LoadingCache sessionCache; - @Autowired - public UserSessionService(ConfigurationService configurationService) { + @Autowired + public UserSessionService(ConfigurationService configurationService) { - LOG.debug("Initializing in-memory session service"); + LOG.debug("Initializing in-memory session service"); - sessionCache = CacheBuilder.newBuilder().maximumSize(100000) - .expireAfterAccess(configurationService.getConfiguration().getSessionConfiguration().getDuration(), - TimeUnit.MINUTES) - .build(new CacheLoader() { - public UserSession load(String o) { - return new UserSession(); - } - }); + sessionCache = CacheBuilder.newBuilder().maximumSize(100000) + .expireAfterAccess(configurationService.getConfiguration().getSessionConfiguration().getDuration(), + TimeUnit.MINUTES) + .build(new CacheLoader() { + public UserSession load(String o) { + return new UserSession(); + } + }); - LOG.debug("* Successfully created session cache"); - } + LOG.debug("* Successfully created session cache"); + } - public UserSession createUserSession() { - LOG.debug("Creating new session"); + public UserSession createUserSession() { + LOG.debug("Creating new session"); - String sessionId = UUID.randomUUID().toString(); + String sessionId = UUID.randomUUID().toString(); - UserSession session = new UserSession(); - session.setId(sessionId); - sessionCache.put(sessionId, session); + UserSession session = new UserSession(); + session.setId(sessionId); + sessionCache.put(sessionId, session); - LOG.debug("New session generated {}", sessionId); + LOG.debug("New session generated {}", sessionId); - return session; - } + return session; + } - public UserSession getUserSession(String sessionId) { + public UserSession getUserSession(String sessionId) { - UserSession userSession = null; + UserSession userSession = null; - if (sessionId != null) { + if (sessionId != null) { - LOG.debug("Fetch session {} in cache", sessionId); + LOG.debug("Fetch session {} in cache", sessionId); - try { - userSession = sessionCache.get(sessionId); - } catch (ExecutionException ex) { - LOG.error("An error occured when loading session from cache: {}", ex.getMessage()); - LOG.debug("* Detailed Stacktrace: ", ex); - } - } + try { + userSession = sessionCache.get(sessionId); + } catch (ExecutionException ex) { + LOG.error("An error occured when loading session from cache: {}", ex.getMessage()); + LOG.debug("* Detailed Stacktrace: ", ex); + } + } - // Check that the session still exists. If not, we create a new one - if (userSession == null || userSession.getId() == null) { + // Check that the session still exists. If not, we create a new one + if (userSession == null || userSession.getId() == null) { - LOG.debug("No existing session found"); + LOG.debug("No existing session found"); - userSession = createUserSession(); - } + userSession = createUserSession(); + } - return userSession; - } + return userSession; + } - public void removeUserSession(String userSessionId) { + public void removeUserSession(String userSessionId) { - LOG.debug("Remove session {} from cache", userSessionId); + LOG.debug("Remove session {} from cache", userSessionId); - sessionCache.invalidate(userSessionId); + sessionCache.invalidate(userSessionId); - } + } } diff --git a/src/main/java/net/identio/server/utils/DecodeUtils.java b/src/main/java/net/identio/server/utils/DecodeUtils.java index 1b16f52..2e16a57 100644 --- a/src/main/java/net/identio/server/utils/DecodeUtils.java +++ b/src/main/java/net/identio/server/utils/DecodeUtils.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.utils; @@ -32,142 +33,134 @@ License, or (at your option) any later version. public class DecodeUtils { - private static final Logger LOG = LoggerFactory.getLogger(DecodeUtils.class); + private static final Logger LOG = LoggerFactory.getLogger(DecodeUtils.class); + + /** + * Utility method to Base64-decode and eventually inflate a string + * + * @param value Value to decode + * @param isDeflated Indicates if the string should be inflated + * @return + * @throws Base64DecodingException + * @throws DataFormatException + * @throws Exception + */ + public static byte[] decode(String data, boolean inflate) + throws IOException, Base64DecodingException, DataFormatException { + + LOG.debug("Decoding string {} with inflate = {}", data, inflate); + + // First, we decode the B64 string + byte[] decodedBytes = Base64.decode(data); + + if (inflate) { + try { + // try DEFLATE (rfc 1951) -- according to SAML spec + decodedBytes = inflate(decodedBytes, true); + + } catch (IOException ze) { + // try zlib (rfc 1950) + decodedBytes = inflate(decodedBytes, false); + } + } + + LOG.debug("Finished decoding string"); + + return decodedBytes; + } + + /** + * Utility method to Base64-encode and eventually deflate data + * + * @param value Value to encode + * @param deflate Indicates if the string should be deflated + * @return Encoded string + * @throws IOException + */ + public static String encode(byte[] data, boolean deflate) throws IOException { + + LOG.debug("Encoding data in base 64 with deflate = {}", deflate); + + String encodedString = null; + + byte[] deflatedData = deflate ? deflate(data, true) : data; + + // First, we decode the B64 string + encodedString = Base64.encode(deflatedData).replaceAll("\r", "").replaceAll("\n", ""); + + LOG.debug("Encoded string: {}", encodedString); + + return encodedString; + } + + /** + * Utility method to inflate a compressed string + * + * @param bytes Bytes to decode + * @param nowrap Should wrapping be used + * @return Decoded bytes + * @throws IOException + * @throws DataFormatException + * @throws Exception + */ + private static byte[] inflate(byte[] data, boolean nowrap) throws IOException, DataFormatException { + + LOG.debug("Inflating string with nowrap = {}...", nowrap); + + Inflater decompressor = new Inflater(nowrap); + decompressor.setInput(data); + + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + + byte[] buf = new byte[512]; + + while (!decompressor.finished()) { + int count = decompressor.inflate(buf); + out.write(buf, 0, count); + } + + LOG.debug("String inflated successfully"); + + return out.toByteArray(); + + } finally { + if (decompressor != null) + decompressor.end(); + } + } + + /** + * Utility method to deflate an uncompressed string + * + * @param bytes Bytes to decode + * @param nowrap Should wrapping be used + * @return Decoded bytes + * @throws IOException + * @throws Exception + */ + private static byte[] deflate(byte[] data, boolean nowrap) throws IOException { + + LOG.debug("Deflating string with nowrap = {}...", nowrap); + + Deflater deflater = new Deflater(7, nowrap); + deflater.setInput(data); + deflater.finish(); + + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) { + + byte[] buffer = new byte[1024]; - /** - * Utility method to Base64-decode and eventually inflate a string - * - * @param value - * Value to decode - * @param isDeflated - * Indicates if the string should be inflated - * @return - * @throws Base64DecodingException - * @throws DataFormatException - * @throws Exception - */ - public static byte[] decode(String data, boolean inflate) - throws IOException, Base64DecodingException, DataFormatException { - - LOG.debug("Decoding string {} with inflate = {}", data, inflate); - - // First, we decode the B64 string - byte[] decodedBytes = Base64.decode(data); - - if (inflate) { - try { - // try DEFLATE (rfc 1951) -- according to SAML spec - decodedBytes = inflate(decodedBytes, true); - - } catch (IOException ze) { - // try zlib (rfc 1950) - decodedBytes = inflate(decodedBytes, false); - } - } - - LOG.debug("Finished decoding string"); - - return decodedBytes; - } - - /** - * Utility method to Base64-encode and eventually deflate data - * - * @param value - * Value to encode - * @param deflate - * Indicates if the string should be deflated - * @return Encoded string - * @throws IOException - */ - public static String encode(byte[] data, boolean deflate) throws IOException { - - LOG.debug("Encoding data in base 64 with deflate = {}", deflate); - - String encodedString = null; - - byte[] deflatedData = deflate ? deflate(data, true) : data; - - // First, we decode the B64 string - encodedString = Base64.encode(deflatedData).replaceAll("\r", "").replaceAll("\n", ""); - - LOG.debug("Encoded string: {}", encodedString); - - return encodedString; - } - - /** - * Utility method to inflate a compressed string - * - * @param bytes - * Bytes to decode - * @param nowrap - * Should wrapping be used - * @return Decoded bytes - * @throws IOException - * @throws DataFormatException - * @throws Exception - */ - private static byte[] inflate(byte[] data, boolean nowrap) throws IOException, DataFormatException { - - LOG.debug("Inflating string with nowrap = {}...", nowrap); - - Inflater decompressor = new Inflater(nowrap); - decompressor.setInput(data); - - try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { - - byte[] buf = new byte[512]; - - while (!decompressor.finished()) { - int count = decompressor.inflate(buf); - out.write(buf, 0, count); - } - - LOG.debug("String inflated successfully"); - - return out.toByteArray(); - - } finally { - if (decompressor != null) - decompressor.end(); - } - } - - /** - * Utility method to deflate an uncompressed string - * - * @param bytes - * Bytes to decode - * @param nowrap - * Should wrapping be used - * @return Decoded bytes - * @throws IOException - * @throws Exception - */ - private static byte[] deflate(byte[] data, boolean nowrap) throws IOException { - - LOG.debug("Deflating string with nowrap = {}...", nowrap); + while (!deflater.finished()) { + int count = deflater.deflate(buffer); + outputStream.write(buffer, 0, count); + } - Deflater deflater = new Deflater(7, nowrap); - deflater.setInput(data); - deflater.finish(); - - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length)) { - - byte[] buffer = new byte[1024]; - - while (!deflater.finished()) { - int count = deflater.deflate(buffer); - outputStream.write(buffer, 0, count); - } - - outputStream.close(); + outputStream.close(); - return outputStream.toByteArray(); - } finally { - if (deflater != null) - deflater.end(); - } - } + return outputStream.toByteArray(); + } finally { + if (deflater != null) + deflater.end(); + } + } } diff --git a/src/main/java/net/identio/server/utils/FileUtils.java b/src/main/java/net/identio/server/utils/FileUtils.java index e20194d..4024b64 100644 --- a/src/main/java/net/identio/server/utils/FileUtils.java +++ b/src/main/java/net/identio/server/utils/FileUtils.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io. - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.utils; @@ -28,24 +29,24 @@ License, or (at your option) any later version. public class FileUtils { - public static String getFileHash(String filename) throws NoSuchAlgorithmException, IOException { + public static String getFileHash(String filename) throws NoSuchAlgorithmException, IOException { - MessageDigest md = MessageDigest.getInstance("MD5"); - String result = null; + MessageDigest md = MessageDigest.getInstance("MD5"); + String result = null; - md.reset(); + md.reset(); - byte[] buf = new byte[2048]; - int numBytes; + byte[] buf = new byte[2048]; + int numBytes; - try (FileInputStream is = new FileInputStream(filename)) { - while ((numBytes = is.read(buf)) != -1) { - md.update(buf, 0, numBytes); - } + try (FileInputStream is = new FileInputStream(filename)) { + while ((numBytes = is.read(buf)) != -1) { + md.update(buf, 0, numBytes); + } - result = new String(Hex.encode(md.digest())); - } + result = new String(Hex.encode(md.digest())); + } - return result; - } + return result; + } } diff --git a/src/main/java/net/identio/server/utils/HttpUtils.java b/src/main/java/net/identio/server/utils/HttpUtils.java index e53f9c2..dc6d094 100644 --- a/src/main/java/net/identio/server/utils/HttpUtils.java +++ b/src/main/java/net/identio/server/utils/HttpUtils.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.utils; @@ -25,25 +26,25 @@ License, or (at your option) any later version. public class HttpUtils { - public static void setSessionCookie(HttpServletResponse httpResponse, String sessionId, - boolean secure) { + public static void setSessionCookie(HttpServletResponse httpResponse, String sessionId, + boolean secure) { - Cookie sessionCookie = new Cookie("identioSession", sessionId); - sessionCookie.setHttpOnly(true); - sessionCookie.setMaxAge(-1); // Session cookie - sessionCookie.setPath("/"); - sessionCookie.setSecure(secure); - httpResponse.addCookie(sessionCookie); - } + Cookie sessionCookie = new Cookie("identioSession", sessionId); + sessionCookie.setHttpOnly(true); + sessionCookie.setMaxAge(-1); // Session cookie + sessionCookie.setPath("/"); + sessionCookie.setSecure(secure); + httpResponse.addCookie(sessionCookie); + } - public static String getHttpHeader(HttpServletRequest httpRequest, String name) { + public static String getHttpHeader(HttpServletRequest httpRequest, String name) { - String header = httpRequest.getHeader(name); + String header = httpRequest.getHeader(name); - if ("(null)".equals(header)) - return null; + if ("(null)".equals(header)) + return null; - return header; - } + return header; + } } diff --git a/src/main/java/net/identio/server/utils/PasswordUtils.java b/src/main/java/net/identio/server/utils/PasswordUtils.java index 6b19cb5..9af0d84 100644 --- a/src/main/java/net/identio/server/utils/PasswordUtils.java +++ b/src/main/java/net/identio/server/utils/PasswordUtils.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.utils; @@ -25,26 +26,26 @@ License, or (at your option) any later version. public class PasswordUtils { - public static void main(String[] args) { + public static void main(String[] args) { - int rounds = 10; + int rounds = 10; - if (args.length == 1) { - rounds = Integer.parseInt(args[0]); + if (args.length == 1) { + rounds = Integer.parseInt(args[0]); - if (rounds < 4 || rounds > 31) { - System.out.println("Error: valid rounds range is 4-31"); - return; - } - } + if (rounds < 4 || rounds > 31) { + System.out.println("Error: valid rounds range is 4-31"); + return; + } + } - Console console = System.console(); + Console console = System.console(); - char[] password = console.readPassword("Enter password: "); - // String password = "password"; - String hashedPassword = BCrypt.hashpw(new String(password), BCrypt.gensalt(rounds)); + char[] password = console.readPassword("Enter password: "); + // String password = "password"; + String hashedPassword = BCrypt.hashpw(new String(password), BCrypt.gensalt(rounds)); - System.out.println("Hashed password: " + hashedPassword); - } + System.out.println("Hashed password: " + hashedPassword); + } } diff --git a/src/main/java/net/identio/server/utils/SecurityUtils.java b/src/main/java/net/identio/server/utils/SecurityUtils.java index 8957ce5..b4efa0d 100644 --- a/src/main/java/net/identio/server/utils/SecurityUtils.java +++ b/src/main/java/net/identio/server/utils/SecurityUtils.java @@ -1,21 +1,22 @@ /* - This file is part of Ident.io - - Ident.io - A flexible authentication server - Copyright (C) Loeiz TANGUY - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as - published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * */ package net.identio.server.utils; @@ -31,98 +32,98 @@ License, or (at your option) any later version. public class SecurityUtils { - public static final String escapeDN(String name) { - StringBuilder sb = new StringBuilder(); - - if (name.length() > 0 && (name.charAt(0) == ' ' || name.charAt(0) == '#')) { - sb.append('\\'); // add the leading backslash if needed - } - - for (int i = 0; i < name.length(); i++) { - char curChar = name.charAt(i); - switch (curChar) { - case '\\': - sb.append("\\\\"); - break; - case ',': - sb.append("\\,"); - break; - case '+': - sb.append("\\+"); - break; - case '"': - sb.append("\\\""); - break; - case '<': - sb.append("\\<"); - break; - case '>': - sb.append("\\>"); - break; - case ';': - sb.append("\\;"); - break; - default: - sb.append(curChar); - break; - } - } - - if (name.length() > 1 && name.charAt(name.length() - 1) == ' ') { - sb.insert(sb.length() - 1, '\\'); // add the trailing backslash if - // needed - } - - return sb.toString(); - } - - public static final String escapeLDAPSearchFilter(String filter) { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < filter.length(); i++) { - char curChar = filter.charAt(i); - switch (curChar) { - case '\\': - sb.append("\\5c"); - break; - case '*': - sb.append("\\2a"); - break; - case '(': - sb.append("\\28"); - break; - case ')': - sb.append("\\29"); - break; - case '\u0000': - sb.append("\\00"); - break; - default: - sb.append(curChar); - break; - } - } - return sb.toString(); - } - - - public static final void addCertificateToKeyStore(KeyStore ks, X509Certificate cert, String alias) - throws KeyStoreException { - - ks.setCertificateEntry(alias, cert); - } - - public static final X509Certificate parseCertificate(String path) - throws IOException, CertificateException { - - try (FileInputStream fis = new FileInputStream(path); BufferedInputStream bis = new BufferedInputStream(fis)) { - - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - - return (X509Certificate) cf.generateCertificate(bis); - - } - - } + public static final String escapeDN(String name) { + StringBuilder sb = new StringBuilder(); + + if (name.length() > 0 && (name.charAt(0) == ' ' || name.charAt(0) == '#')) { + sb.append('\\'); // add the leading backslash if needed + } + + for (int i = 0; i < name.length(); i++) { + char curChar = name.charAt(i); + switch (curChar) { + case '\\': + sb.append("\\\\"); + break; + case ',': + sb.append("\\,"); + break; + case '+': + sb.append("\\+"); + break; + case '"': + sb.append("\\\""); + break; + case '<': + sb.append("\\<"); + break; + case '>': + sb.append("\\>"); + break; + case ';': + sb.append("\\;"); + break; + default: + sb.append(curChar); + break; + } + } + + if (name.length() > 1 && name.charAt(name.length() - 1) == ' ') { + sb.insert(sb.length() - 1, '\\'); // add the trailing backslash if + // needed + } + + return sb.toString(); + } + + public static final String escapeLDAPSearchFilter(String filter) { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < filter.length(); i++) { + char curChar = filter.charAt(i); + switch (curChar) { + case '\\': + sb.append("\\5c"); + break; + case '*': + sb.append("\\2a"); + break; + case '(': + sb.append("\\28"); + break; + case ')': + sb.append("\\29"); + break; + case '\u0000': + sb.append("\\00"); + break; + default: + sb.append(curChar); + break; + } + } + return sb.toString(); + } + + + public static final void addCertificateToKeyStore(KeyStore ks, X509Certificate cert, String alias) + throws KeyStoreException { + + ks.setCertificateEntry(alias, cert); + } + + public static final X509Certificate parseCertificate(String path) + throws IOException, CertificateException { + + try (FileInputStream fis = new FileInputStream(path); BufferedInputStream bis = new BufferedInputStream(fis)) { + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + return (X509Certificate) cf.generateCertificate(bis); + + } + + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index dbc2532..925a484 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1 +1,21 @@ +# +# This file is part of Ident.io. +# +# Ident.io - A flexible authentication server +# Copyright (c) 2017 Loeiz TANGUY +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# spring.resources.cache-period=500000 \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml index ef6ec44..fcb270c 100644 --- a/src/main/resources/logback.xml +++ b/src/main/resources/logback.xml @@ -1,32 +1,53 @@ + + - + - - - - %magenta(%d{HH:mm:ss.SSS}) %cyan([%thread]) - %highlight(%-5level) %cyan(%logger{5}) - %msg%n - - - + + + + %magenta(%d{HH:mm:ss.SSS}) %cyan([%thread]) + %highlight(%-5level) %cyan(%logger{5}) - %msg%n + + + - - + + - - - - - + + + + + \ No newline at end of file diff --git a/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java b/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java index 184756c..7ec7e63 100644 --- a/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/InitialRequestTests.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.tests.integ.oauth; import net.identio.server.boot.IdentioServerApplication; diff --git a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java index f40b859..d73871f 100644 --- a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java @@ -1,3 +1,24 @@ +/* + * This file is part of Ident.io. + * + * Ident.io - A flexible authentication server + * Copyright (c) 2017 Loeiz TANGUY + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + package net.identio.server.tests.integ.oauth; import com.auth0.jwt.JWT; diff --git a/src/test/resources/oauth-server-config/logback.xml b/src/test/resources/oauth-server-config/logback.xml index 34091fc..e54ee95 100644 --- a/src/test/resources/oauth-server-config/logback.xml +++ b/src/test/resources/oauth-server-config/logback.xml @@ -1,23 +1,44 @@ + + - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n - - - + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{5} - %msg%n + + + - - + + - - - - - + + + + + \ No newline at end of file diff --git a/ui/app/index.html b/ui/app/index.html index e04dedd..6c9807f 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -1,55 +1,56 @@ - - - Ident.io - - - - - - - - - - - - - - - + + + Ident.io + + + + + + + + + + + + + + + - -
-
-
+ +
+
+
- - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/ui/app/views/auth.html b/ui/app/views/auth.html index fb03c63..1d1def0 100644 --- a/ui/app/views/auth.html +++ b/ui/app/views/auth.html @@ -1,52 +1,52 @@
- +
-

{{'IDENTIO_SIGN_IN' | translate}}

+

{{'IDENTIO_SIGN_IN' | translate}}

- - - - -
- -
-

- -
- -
- -
- - -
-
- - -
-

- -
-

- {{method.name}} -

-
-
+ + + + +
+ +
+

+ +
+ +
+ +
+ + +
+
+ + +
+

+ +
+

+ {{method.name}} +

+
+
diff --git a/ui/app/views/challenge.html b/ui/app/views/challenge.html index 0918ff7..3a1ea55 100644 --- a/ui/app/views/challenge.html +++ b/ui/app/views/challenge.html @@ -1,13 +1,12 @@ -

- - + class="glyphicon glyphicon-lock"> + +
diff --git a/ui/app/views/error.html b/ui/app/views/error.html index 88a2603..468fe96 100644 --- a/ui/app/views/error.html +++ b/ui/app/views/error.html @@ -3,12 +3,12 @@
-

+

- - + +
diff --git a/ui/app/views/ldap.html b/ui/app/views/ldap.html index 466e09c..b0702e5 100644 --- a/ui/app/views/ldap.html +++ b/ui/app/views/ldap.html @@ -1,7 +1,7 @@

+ placeholder="Username" ng-model="auth.login">

+ placeholder="Password" ng-model="auth.password"> diff --git a/ui/app/views/local.html b/ui/app/views/local.html index 466e09c..0bee875 100644 --- a/ui/app/views/local.html +++ b/ui/app/views/local.html @@ -1,7 +1,28 @@ + +

+ placeholder="Username" ng-model="auth.login">

+ placeholder="Password" ng-model="auth.password"> diff --git a/ui/app/views/logout.html b/ui/app/views/logout.html index f136f71..3d1655f 100644 --- a/ui/app/views/logout.html +++ b/ui/app/views/logout.html @@ -1,8 +1,8 @@
-
-
-

You're now logged out.

+
+
+

You're now logged out.

-
-
-
\ No newline at end of file +
+
+ diff --git a/ui/app/views/radius.html b/ui/app/views/radius.html index 4b1c6c1..b0702e5 100644 --- a/ui/app/views/radius.html +++ b/ui/app/views/radius.html @@ -1,7 +1,7 @@

+ placeholder="Username" ng-model="auth.login">

\ No newline at end of file + placeholder="Password" ng-model="auth.password"> From df90730b1fd5335381edeb0603c8c1e3e9dc29a7 Mon Sep 17 00:00:00 2001 From: Loeiz Tanguy Date: Thu, 17 Aug 2017 23:20:36 +0200 Subject: [PATCH 030/104] Some minor Codacy fixes --- .../mvc/common/GlobalControllerExceptionHandler.java | 1 - .../server/mvc/common/TransparentAuthController.java | 1 - .../identio/server/mvc/oauth/ConsentController.java | 4 ---- .../authentication/ldap/LdapSslSocketFactory.java | 1 - .../radius/RadiusAuthenticationProvider.java | 1 - .../identio/server/service/oauth/ConsentService.java | 3 --- .../orchestration/AuthOrchestrationService.java | 10 +--------- .../orchestration/ProxyAuthOrchestrationService.java | 2 ++ .../orchestration/RequestOrchestrationService.java | 4 ---- .../java/net/identio/server/utils/SecurityUtils.java | 1 - 10 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java index 6050d80..b9aeb1f 100644 --- a/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java +++ b/src/main/java/net/identio/server/mvc/common/GlobalControllerExceptionHandler.java @@ -24,7 +24,6 @@ import net.identio.server.service.orchestration.exceptions.ValidationException; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.ServletRequestBindingException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java index 2559aaf..36398a7 100644 --- a/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java +++ b/src/main/java/net/identio/server/mvc/common/TransparentAuthController.java @@ -21,7 +21,6 @@ package net.identio.server.mvc.common; import net.identio.server.service.orchestration.exceptions.ServerException; -import net.identio.server.service.orchestration.exceptions.ValidationException; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.service.authentication.model.X509Authentication; import net.identio.server.mvc.saml.ResponderController; diff --git a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java index 1a9105d..6cb54d5 100644 --- a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java +++ b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java @@ -26,16 +26,12 @@ import net.identio.server.mvc.oauth.model.ConsentRequest; import net.identio.server.mvc.oauth.model.ConsentResponse; import net.identio.server.service.oauth.ConsentService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController public class ConsentController { - private static final Logger LOG = LoggerFactory.getLogger(ConsentController.class); - @Autowired private ConsentService consentService; diff --git a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java index cfd4e5b..31d2975 100644 --- a/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java +++ b/src/main/java/net/identio/server/service/authentication/ldap/LdapSslSocketFactory.java @@ -27,7 +27,6 @@ import java.io.IOException; import java.net.InetAddress; import java.net.Socket; -import java.net.UnknownHostException; import java.security.*; public class LdapSslSocketFactory extends SSLSocketFactory { diff --git a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java index fa27c2e..d86aabb 100644 --- a/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java +++ b/src/main/java/net/identio/server/service/authentication/radius/RadiusAuthenticationProvider.java @@ -20,7 +20,6 @@ */ package net.identio.server.service.authentication.radius; -import net.identio.server.exceptions.InitializationException; import net.identio.server.model.*; import net.identio.server.service.authentication.AuthenticationProvider; import net.identio.server.service.authentication.AuthenticationService; diff --git a/src/main/java/net/identio/server/service/oauth/ConsentService.java b/src/main/java/net/identio/server/service/oauth/ConsentService.java index 4a6a511..c2ebd26 100644 --- a/src/main/java/net/identio/server/service/oauth/ConsentService.java +++ b/src/main/java/net/identio/server/service/oauth/ConsentService.java @@ -21,7 +21,6 @@ package net.identio.server.service.oauth; -import net.identio.server.service.orchestration.exceptions.ValidationException; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.model.AuthorizationScope; import net.identio.server.service.transaction.model.TransactionData; @@ -38,8 +37,6 @@ @Service public class ConsentService { - private static final Logger LOG = LoggerFactory.getLogger(ConsentService.class); - @Autowired private TransactionService transactionService; diff --git a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java index a34d517..e588f44 100644 --- a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java @@ -27,7 +27,6 @@ import net.identio.server.service.authentication.model.Authentication; import net.identio.server.service.authentication.model.AuthenticationResult; import net.identio.server.service.authentication.model.AuthenticationResultStatus; -import net.identio.server.service.authentication.saml.SamlAuthenticationProvider; import net.identio.server.service.authpolicy.AuthPolicyService; import net.identio.server.service.authpolicy.model.AuthPolicyDecision; import net.identio.server.service.authpolicy.model.AuthPolicyDecisionStatus; @@ -39,7 +38,6 @@ import net.identio.server.service.transaction.model.TransactionData; import net.identio.server.service.transaction.TransactionService; import net.identio.server.service.transaction.model.TransactionState; -import net.identio.server.service.usersession.UserSessionService; import net.identio.server.service.orchestration.model.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,9 +53,6 @@ public class AuthOrchestrationService { private static final Logger LOG = LoggerFactory.getLogger(AuthOrchestrationService.class); - @Autowired - private UserSessionService userSessionService; - @Autowired private SamlService samlService; @@ -73,9 +68,6 @@ public class AuthOrchestrationService { @Autowired private AuthenticationService authenticationService; - @Autowired - private SamlAuthenticationProvider samlAuthenticationProvider; - public AuthenticationValidationResult handleTransparentAuthentication(Authentication authentication, String sessionId, String transactionId) throws WebSecurityException, ServerException { @@ -129,7 +121,7 @@ public AuthenticationValidationResult handleExplicitAuthentication(String transa validationResult.setProtocolType(transactionData.getProtocolType()); // Try to map the auth method name to a known method - AuthMethod authMethod = null; + AuthMethod authMethod; try { diff --git a/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java index 784d6ec..6eb9bd6 100644 --- a/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/ProxyAuthOrchestrationService.java @@ -57,6 +57,8 @@ public SamlAuthRequestGenerationResult initSamlRequest(String transactionId, Str String authMethodName) throws ValidationException, WebSecurityException, ServerException { + LOG.debug("Start generation of a SAML request"); + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); // Check that we are in the correct transaction state diff --git a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java index 45b7944..f13183a 100644 --- a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java @@ -35,8 +35,6 @@ import net.identio.server.service.transaction.model.TransactionState; import net.identio.server.service.usersession.UserSessionService; import net.identio.server.service.orchestration.model.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -46,8 +44,6 @@ @Service public class RequestOrchestrationService { - private static final Logger LOG = LoggerFactory.getLogger(RequestOrchestrationService.class); - @Autowired private TransactionService transactionService; diff --git a/src/main/java/net/identio/server/utils/SecurityUtils.java b/src/main/java/net/identio/server/utils/SecurityUtils.java index b4efa0d..2f9de43 100644 --- a/src/main/java/net/identio/server/utils/SecurityUtils.java +++ b/src/main/java/net/identio/server/utils/SecurityUtils.java @@ -22,7 +22,6 @@ import java.io.BufferedInputStream; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.IOException; import java.security.KeyStore; import java.security.KeyStoreException; From c30a2abd8ceed1e1f3afdfe7e33d0898c955819f Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 29 Aug 2017 11:59:09 +0200 Subject: [PATCH 031/104] Removed unused exceptions --- .../exceptions/AuthenticationException.java | 34 ------------------- .../NoAuthMethodFoundException.java | 34 ------------------- 2 files changed, 68 deletions(-) delete mode 100644 src/main/java/net/identio/server/exceptions/AuthenticationException.java delete mode 100644 src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java diff --git a/src/main/java/net/identio/server/exceptions/AuthenticationException.java b/src/main/java/net/identio/server/exceptions/AuthenticationException.java deleted file mode 100644 index 8ef7838..0000000 --- a/src/main/java/net/identio/server/exceptions/AuthenticationException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Ident.io. - * - * Ident.io - A flexible authentication server - * Copyright (c) 2017 Loeiz TANGUY - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -package net.identio.server.exceptions; - -public class AuthenticationException extends Exception { - - private static final long serialVersionUID = 7980689067621954038L; - - public AuthenticationException(String s) { - super(s); - } - - public AuthenticationException(String s, Throwable e) { - super(s, e); - } -} diff --git a/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java b/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java deleted file mode 100644 index ba6e781..0000000 --- a/src/main/java/net/identio/server/exceptions/NoAuthMethodFoundException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of Ident.io. - * - * Ident.io - A flexible authentication server - * Copyright (c) 2017 Loeiz TANGUY - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ -package net.identio.server.exceptions; - -public class NoAuthMethodFoundException extends Exception { - - private static final long serialVersionUID = -7484071565697761702L; - - public NoAuthMethodFoundException(String s) { - super(s); - } - - public NoAuthMethodFoundException(String s, Throwable e) { - super(s, e); - } -} From 4166b5b29015e8eeedc0bac218f35db1d08d8782 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 29 Aug 2017 16:31:55 +0200 Subject: [PATCH 032/104] Simplified responses from servers --- .../server/mvc/common/AuthentController.java | 4 +-- .../mvc/common/model/AuthSubmitResponse.java | 31 ++++--------------- ui/app/scripts/app.js | 2 -- ui/app/scripts/controllers/authController.js | 8 ++--- ui/app/scripts/directives/saml-responder.js | 2 +- 5 files changed, 12 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/common/AuthentController.java b/src/main/java/net/identio/server/mvc/common/AuthentController.java index d1db698..a61b7cf 100644 --- a/src/main/java/net/identio/server/mvc/common/AuthentController.java +++ b/src/main/java/net/identio/server/mvc/common/AuthentController.java @@ -76,9 +76,7 @@ public AuthSubmitResponse authenticationSubmit(HttpServletRequest httpRequest, case RESPONSE: response.setStatus(ApiResponseStatus.RESPONSE) - .setDestinationUrl(result.getResponseData().getUrl()) - .setRelayState(result.getResponseData().getRelayState()) - .setData(result.getResponseData().getData()) + .setResponseData(result.getResponseData()) .setProtocolType(result.getProtocolType()); break; diff --git a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java index 6fedb08..2e59226 100644 --- a/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java +++ b/src/main/java/net/identio/server/mvc/common/model/AuthSubmitResponse.java @@ -23,15 +23,14 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude.Include; import net.identio.server.model.ProtocolType; +import net.identio.server.service.orchestration.model.ResponseData; @JsonInclude(Include.NON_NULL) public class AuthSubmitResponse { private ApiResponseStatus status; private String errorStatus; - private String destinationUrl; - private String relayState; - private String data; + private ResponseData responseData; private ProtocolType protocolType; private String challengeType; private String challengeValue; @@ -54,30 +53,12 @@ public AuthSubmitResponse setErrorStatus(String errorStatus) { return this; } - public String getDestinationUrl() { - return destinationUrl; + public ResponseData getResponseData() { + return responseData; } - public AuthSubmitResponse setDestinationUrl(String destinationUrl) { - this.destinationUrl = destinationUrl; - return this; - } - - public String getRelayState() { - return relayState; - } - - public AuthSubmitResponse setRelayState(String relayState) { - this.relayState = relayState; - return this; - } - - public String getData() { - return data; - } - - public AuthSubmitResponse setData(String data) { - this.data = data; + public AuthSubmitResponse setResponseData(ResponseData responseData) { + this.responseData = responseData; return this; } diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index 6469511..e67a46e 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -64,7 +64,6 @@ 'auth.method.unknown': 'The authentication method is unknown', 'auth.method.not.allowed': 'The authentication method is not allowed', 'invalid.transaction': 'The transaction identifier is invalid or expired', - 'invalid.request': 'The received request is invalid' }) .translations('fr', { @@ -92,7 +91,6 @@ 'auth.method.unknown': 'La méthode d’authentification est inconnue', 'auth.method.not.allowed': 'La méthode d’authentification est invalide', 'invalid.transaction': 'L’identifiant de transaction est invalide ou expiré', - 'invalid.request': 'La requête reçue est invalide' }) .registerAvailableLanguageKeys(['en', 'fr'], { 'en_US': 'en', diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index a7a05f6..7220259 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -100,14 +100,14 @@ if (data.status === 'RESPONSE') { - data.destinationUrl = $sce - .trustAsResourceUrl(data.destinationUrl); + data.responseData.url = $sce + .trustAsResourceUrl(data.responseData.url); if (data.protocolType === 'SAML') { - $rootScope.$broadcast('saml.submit.response', data); + $rootScope.$broadcast('saml.submit.response', data.responseData); } if (data.protocolType === 'OAUTH') { - $rootScope.$broadcast('oauth.submit.response', data); + $rootScope.$broadcast('oauth.submit.response', data.responseData); } return; diff --git a/ui/app/scripts/directives/saml-responder.js b/ui/app/scripts/directives/saml-responder.js index 95d8537..dca248e 100644 --- a/ui/app/scripts/directives/saml-responder.js +++ b/ui/app/scripts/directives/saml-responder.js @@ -10,7 +10,7 @@ angular.module('identioUiApp') return { replace: true, scope: {}, - template: '
'+ + template: ''+ ''+ ''+ '
', From 9363eaec95183c94e8ee3d9558ae4ba66ba0ea14 Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Tue, 29 Aug 2017 16:34:23 +0200 Subject: [PATCH 033/104] Implemented server-side consent handling --- .../server/model/AuthorizationScope.java | 15 +++ .../server/mvc/oauth/ConsentController.java | 7 +- .../mvc/oauth/model/ConsentResponse.java | 12 +- .../mvc/saml/RequestConsumerController.java | 9 -- .../authorization/AuthorizationService.java | 10 +- .../server/service/oauth/ConsentService.java | 46 ++++++- .../server/service/oauth/OAuthService.java | 22 ++-- .../service/oauth/model/OAuthClient.java | 11 +- .../AuthOrchestrationService.java | 114 +++++++++--------- .../RequestOrchestrationService.java | 35 +++--- .../model/OrchestrationErrorStatus.java | 2 +- .../model/RequestParsingInfo.java | 20 ++- .../oauth/OAuthImplicitFullCinematicTest.java | 26 ++-- .../oauth-server-config/identio-config.yml | 3 + .../oauth-server-config/oauth-clients.yml | 2 +- 15 files changed, 199 insertions(+), 135 deletions(-) diff --git a/src/main/java/net/identio/server/model/AuthorizationScope.java b/src/main/java/net/identio/server/model/AuthorizationScope.java index fc24cd7..e75ad13 100644 --- a/src/main/java/net/identio/server/model/AuthorizationScope.java +++ b/src/main/java/net/identio/server/model/AuthorizationScope.java @@ -20,11 +20,16 @@ */ package net.identio.server.model; +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.HashMap; + public class AuthorizationScope { private String name; private AuthLevel authLevel; private int expirationTime; + private HashMap description; public String getName() { return name; @@ -50,9 +55,19 @@ public void setExpirationTime(int expirationTime) { this.expirationTime = expirationTime; } + public HashMap getDescription() { + return description; + } + + public void setDescription(HashMap description) { + this.description = description; + } + + @JsonIgnore public AuthorizationScope getPublicCopy() { AuthorizationScope response = new AuthorizationScope(); response.setName(this.name); + response.setDescription(this.description); return response; } diff --git a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java index 6cb54d5..e004c65 100644 --- a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java +++ b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java @@ -20,7 +20,6 @@ */ package net.identio.server.mvc.oauth; -import net.identio.server.service.orchestration.exceptions.ValidationException; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.mvc.oauth.model.ConsentContext; import net.identio.server.mvc.oauth.model.ConsentRequest; @@ -38,7 +37,7 @@ public class ConsentController { @RequestMapping(value = "/api/authz/consent", method = RequestMethod.GET) public ConsentContext getConsentContext(@RequestHeader(value = "X-Transaction-ID") String transactionId, @CookieValue("identioSession") String sessionId) - throws ValidationException, WebSecurityException { + throws WebSecurityException { return consentService.getConsentContext(transactionId, sessionId); @@ -47,9 +46,9 @@ public ConsentContext getConsentContext(@RequestHeader(value = "X-Transaction-ID @RequestMapping(value = "/api/authz/consent", method = RequestMethod.POST) public ConsentResponse receiveConsent(@RequestBody ConsentRequest consentRequest, @RequestHeader(value = "X-Transaction-ID") String transactionId, - @CookieValue("identioSession") String sessionId) { + @CookieValue("identioSession") String sessionId) throws WebSecurityException { - return new ConsentResponse(); + return consentService.validateConsent(consentRequest, transactionId, sessionId); } } diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java index fb889c7..30a53d1 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java @@ -21,24 +21,28 @@ package net.identio.server.mvc.oauth.model; +import net.identio.server.service.orchestration.model.ResponseData; + public class ConsentResponse { private boolean success; - private String response; + private ResponseData response; public boolean isSuccess() { return success; } - public void setSuccess(boolean success) { + public ConsentResponse setSuccess(boolean success) { this.success = success; + return this; } - public String getResponse() { + public ResponseData getResponseData() { return response; } - public void setResponse(String response) { + public ConsentResponse setResponseData(ResponseData response) { this.response = response; + return this; } } diff --git a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java index 6dd155e..d4d598f 100644 --- a/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java +++ b/src/main/java/net/identio/server/mvc/saml/RequestConsumerController.java @@ -87,15 +87,6 @@ public String samlConsumerPost(HttpServletRequest httpRequest, HttpServletRespon } - /** - * Receives a request through HTTP redirect binding - * - * @throws ServerException - * @throws NoAuthMethodFoundException - * @throws UnknownAuthLevelException - * @throws SamlException - * @throws ValidationException - */ @RequestMapping(value = "/SAML2/SSO/Redirect", method = RequestMethod.GET) public String samlConsumerRedirect(HttpServletRequest httpRequest, HttpServletResponse httpResponse, @RequestParam("SAMLRequest") String usSamlRequest, diff --git a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java index 7c770f2..88a7bef 100644 --- a/src/main/java/net/identio/server/service/authorization/AuthorizationService.java +++ b/src/main/java/net/identio/server/service/authorization/AuthorizationService.java @@ -29,8 +29,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.ArrayList; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; @Service @@ -59,9 +59,9 @@ public AuthorizationService(ConfigurationService configurationService) { } - public List getScopes(List scopeNames) throws UnknownScopeException, NoScopeProvidedException { + public LinkedHashMap getScopes(List scopeNames) throws UnknownScopeException, NoScopeProvidedException { - List scopeList = new ArrayList<>(); + LinkedHashMap result = new LinkedHashMap<>(); if (scopeNames.isEmpty()) { throw new NoScopeProvidedException("Scope list is empty"); @@ -69,12 +69,12 @@ public List getScopes(List scopeNames) throws Unknow for (String scopeName : scopeNames) { if (scopes.containsKey(scopeName)) { - scopeList.add(scopes.get(scopeName)); + result.put(scopeName, scopes.get(scopeName)); } else { throw new UnknownScopeException("Unknown scope: " + scopeName); } } - return scopeList; + return result; } } diff --git a/src/main/java/net/identio/server/service/oauth/ConsentService.java b/src/main/java/net/identio/server/service/oauth/ConsentService.java index c2ebd26..fea11ff 100644 --- a/src/main/java/net/identio/server/service/oauth/ConsentService.java +++ b/src/main/java/net/identio/server/service/oauth/ConsentService.java @@ -21,11 +21,16 @@ package net.identio.server.service.oauth; +import net.identio.server.mvc.oauth.model.ConsentRequest; +import net.identio.server.mvc.oauth.model.ConsentResponse; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.model.AuthorizationScope; +import net.identio.server.service.orchestration.model.OrchestrationErrorStatus; +import net.identio.server.service.orchestration.model.ResponseData; import net.identio.server.service.transaction.model.TransactionData; import net.identio.server.mvc.oauth.model.ConsentContext; import net.identio.server.service.transaction.TransactionService; +import net.identio.server.service.transaction.model.TransactionState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -40,20 +45,53 @@ public class ConsentService { @Autowired private TransactionService transactionService; + @Autowired + private OAuthService oAuthService; + public ConsentContext getConsentContext(String transactionId, String sessionId) throws WebSecurityException { - TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + TransactionData transactionData = getTransactionData(transactionId, sessionId); List authorizedScopes = transactionData .getRequestParsingInfo() - .getRequestedScopes().stream() + .getRequestedScopes().values().stream() .map(AuthorizationScope::getPublicCopy) .collect(Collectors.toList()); return new ConsentContext().setRequestedScopes(authorizedScopes) - .setAudience(transactionData.getRequestParsingInfo().getSourceApplicationName()) - .setAudienceLogo(""); + .setAudience(transactionData.getRequestParsingInfo().getSourceApplicationName()); + + } + + public ConsentResponse validateConsent(ConsentRequest consentRequest, String transactionId, String sessionId) throws WebSecurityException { + + TransactionData transactionData = getTransactionData(transactionId, sessionId); + + // Check that each validated scope is in the requested scopes + for (String scopeName : consentRequest.getApprovedScopes()) { + if (!transactionData.getRequestParsingInfo().getRequestedScopes().containsKey(scopeName)) { + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_SCOPE); + } + } + + return new ConsentResponse().setSuccess(true) + .setResponseData( + oAuthService.generateSuccessResponse(transactionData.getRequestParsingInfo(), + transactionData.getUserSession()) + ); + } + + private TransactionData getTransactionData(String transactionId, String sessionId) throws WebSecurityException { + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + // Check that we are in the correct transaction state + if (transactionData.getState() != TransactionState.CONSENT) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); + } + return transactionData; } } diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 4d4d976..037f0e3 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -50,9 +50,7 @@ import java.security.UnrecoverableEntryException; import java.security.cert.CertificateException; import java.security.interfaces.RSAKey; -import java.util.Enumeration; -import java.util.List; -import java.util.UUID; +import java.util.*; @Service public class OAuthService { @@ -135,7 +133,7 @@ public RequestParsingInfo validateAuthentRequest(OAuthInboundRequest request) { } // Validate scope value - List scopes; + LinkedHashMap scopes; try { scopes = authorizationService.getScopes(request.getScopes()); } catch (UnknownScopeException | NoScopeProvidedException e) { @@ -149,7 +147,7 @@ public RequestParsingInfo validateAuthentRequest(OAuthInboundRequest request) { } result.setStatus(RequestParsingStatus.OK).setSourceApplicationName(client.getName()).setResponseUrl(redirectUri) - .setRequestedScopes(scopes).setResponseType(request.getResponseType()); + .setRequestedScopes(scopes).setResponseType(request.getResponseType()).setConsentNeeded(client.isConsentNeeded()); return result; } @@ -160,25 +158,23 @@ public ResponseData generateSuccessResponse(RequestParsingInfo result, UserSessi responseBuilder.append(result.getResponseUrl()).append("#expires_in="); - // Determine expiration time of the authorization + // Determine expiration time of the authorization and scope string int expirationTime = -1; - for (AuthorizationScope scope : result.getRequestedScopes()) { + StringBuilder scopeBuilder = new StringBuilder(); + + for (AuthorizationScope scope : result.getRequestedScopes().values()) { int scopeExpirationTime = scope.getExpirationTime() != 0 ? scope.getExpirationTime() : 3600; if (expirationTime == -1 || scopeExpirationTime < expirationTime) { expirationTime = scopeExpirationTime; } - } - - responseBuilder.append(expirationTime); - // Calculate scope string - StringBuilder scopeBuilder = new StringBuilder(); - for (AuthorizationScope scope : result.getRequestedScopes()) { scopeBuilder.append(scope.getName()).append(' '); } + responseBuilder.append(expirationTime); + scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java index 0d6c006..d9beede 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthClient.java @@ -30,8 +30,7 @@ public class OAuthClient { private List allowedScopes; private List responseUri; private List allowedGrants; - - private boolean needConsent; + private boolean consentNeeded; public String getName() { return name; @@ -81,11 +80,11 @@ public void setAllowedGrants(List allowedGrants) { this.allowedGrants = allowedGrants; } - public boolean isNeedConsent() { - return needConsent; + public boolean isConsentNeeded() { + return consentNeeded; } - public void setNeedConsent(boolean needConsent) { - this.needConsent = needConsent; + public void setConsentNeeded(boolean consentNeeded) { + this.consentNeeded = consentNeeded; } } diff --git a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java index e588f44..d92e8ee 100644 --- a/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/AuthOrchestrationService.java @@ -75,32 +75,10 @@ public AuthenticationValidationResult handleTransparentAuthentication(Authentica LOG.debug("Check for transparent authentication"); TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); - UserSession userSession = transactionData.getUserSession(); - AuthenticationResult result = authenticationService.validateTransparent(authentication, transactionData); + AuthenticationResult authResult = authenticationService.validateTransparent(authentication, transactionData); - if (result != null && result.getStatus() == AuthenticationResultStatus.SUCCESS) { - - AuthPolicyDecision decision = authPolicyService.checkAuthPolicyCompliance(userSession, result, - transactionData.getTargetAuthLevels()); - - if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { - - try { - - return new AuthenticationValidationResult().setValidationStatus(ValidationStatus.RESPONSE) - .setResponseData(generateSuccessResponse(decision, - transactionData.getRequestParsingInfo(), userSession)); - - } catch (SamlException e) { - throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); - } finally { - transactionService.removeTransactionData(transactionData); - } - } - } - - return new AuthenticationValidationResult().setValidationStatus(ValidationStatus.AUTH); + return decideResponse(authResult, transactionData); } public AuthenticationValidationResult handleExplicitAuthentication(String transactionId, String sessionId, @@ -141,6 +119,39 @@ public AuthenticationValidationResult handleExplicitAuthentication(String transa AuthenticationResult authResult = authenticationService.validateExplicit(authMethod, authentication, transactionData); + return decideResponse(authResult, transactionData); + } + + public List getAuthMethods(String transactionId, String sessionId) throws WebSecurityException { + + TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); + + // Check that we are in the correct transaction state + if (transactionData.getState() != TransactionState.AUTH) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); + } + + return transactionData.getTargetAuthMethods().stream().filter(AuthMethod::isExplicit) + .sorted(Comparator.comparing(AuthMethod::getName)).collect(Collectors.toList()); + + } + + private ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo parsingInfo, + UserSession userSession) throws SamlException { + + if (parsingInfo.getProtocolType() == ProtocolType.SAML) { + return samlService.generateSuccessResponse(decision, parsingInfo, userSession); + } else { + return oauthService.generateSuccessResponse(parsingInfo, userSession); + } + } + + private AuthenticationValidationResult decideResponse(AuthenticationResult authResult, TransactionData transactionData) throws ServerException { + + AuthenticationValidationResult validationResult = new AuthenticationValidationResult(); + validationResult.setProtocolType(transactionData.getProtocolType()); + switch (authResult.getStatus()) { case SUCCESS: @@ -150,18 +161,26 @@ public AuthenticationValidationResult handleExplicitAuthentication(String transa if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { - try { - validationResult.setValidationStatus(ValidationStatus.RESPONSE) - .setResponseData(generateSuccessResponse( - decision, - transactionData.getRequestParsingInfo(), - transactionData.getUserSession())); - - } catch (SamlException e) { - throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); - } finally { - transactionService.removeTransactionData(transactionData); + if (transactionData.getRequestParsingInfo().isConsentNeeded()) { + validationResult.setValidationStatus(ValidationStatus.CONSENT); + transactionData.setState(TransactionState.CONSENT); + + } else { + + try { + validationResult.setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateSuccessResponse( + decision, + transactionData.getRequestParsingInfo(), + transactionData.getUserSession())); + + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } finally { + transactionService.removeTransactionData(transactionData); + } } + } break; @@ -180,29 +199,4 @@ public AuthenticationValidationResult handleExplicitAuthentication(String transa return validationResult; } - - public List getAuthMethods(String transactionId, String sessionId) throws WebSecurityException { - - TransactionData transactionData = transactionService.getTransaction(sessionId, transactionId); - - // Check that we are in the correct transaction state - if (transactionData.getState() != TransactionState.AUTH) { - transactionService.removeTransactionData(transactionData); - throw new WebSecurityException(OrchestrationErrorStatus.INVALID_TRANSACTION); - } - - return transactionData.getTargetAuthMethods().stream().filter(AuthMethod::isExplicit) - .sorted(Comparator.comparing(AuthMethod::getName)).collect(Collectors.toList()); - - } - - private ResponseData generateSuccessResponse(AuthPolicyDecision decision, RequestParsingInfo parsingInfo, - UserSession userSession) throws SamlException { - - if (parsingInfo.getProtocolType() == ProtocolType.SAML) { - return samlService.generateSuccessResponse(decision, parsingInfo, userSession); - } else { - return oauthService.generateSuccessResponse(parsingInfo, userSession); - } - } } diff --git a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java index f13183a..98b6745 100644 --- a/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java +++ b/src/main/java/net/identio/server/service/orchestration/RequestOrchestrationService.java @@ -86,6 +86,8 @@ public RequestValidationResult validateRequest(InboundRequest request, String se UserSession userSession = userSessionService.getUserSession(sessionId); transactionData.setUserSession(userSession); transactionData.setProtocolType(parsingInfo.getProtocolType()); + transactionData.setRequestParsingInfo(parsingInfo); + validationResult.setTransactionId(transactionData.getTransactionId()); validationResult.setSessionId(userSession.getId()); @@ -94,32 +96,31 @@ public RequestValidationResult validateRequest(InboundRequest request, String se ArrayList targetAuthLevels = authPolicyService.determineTargetAuthLevel(parsingInfo); HashSet targetAuthMethods = authPolicyService.determineTargetAuthMethods(targetAuthLevels); + transactionData.setTargetAuthLevels(targetAuthLevels); + transactionData.setTargetAuthMethods(targetAuthMethods); + // Check if previous authentications match AuthPolicyDecision decision = authPolicyService.checkPreviousAuthSessions(userSession, targetAuthLevels); if (decision.getStatus() == AuthPolicyDecisionStatus.OK) { - try { + if (transactionData.getRequestParsingInfo().isConsentNeeded()) { + validationResult.setValidationStatus(ValidationStatus.CONSENT); + transactionData.setState(TransactionState.CONSENT); - validationResult.setValidationStatus(ValidationStatus.RESPONSE) - .setResponseData(generateSuccessResponse(decision, parsingInfo, userSession)); - - } catch (SamlException e) { - throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); - } finally { - transactionService.removeTransactionData(transactionData); + } else { + try { + validationResult.setValidationStatus(ValidationStatus.RESPONSE) + .setResponseData(generateSuccessResponse(decision, parsingInfo, userSession)); + } catch (SamlException e) { + throw new ServerException(OrchestrationErrorStatus.SERVER_ERROR); + } finally { + transactionService.removeTransactionData(transactionData); + } } - - } else { - - validationResult.setValidationStatus(ValidationStatus.AUTH); - - // Save data that will need later in the transaction transactionData.setState(TransactionState.AUTH); - transactionData.setRequestParsingInfo(parsingInfo); - transactionData.setTargetAuthLevels(targetAuthLevels); - transactionData.setTargetAuthMethods(targetAuthMethods); + validationResult.setValidationStatus(ValidationStatus.AUTH); } return validationResult; diff --git a/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java index 7530d2e..b241149 100644 --- a/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java +++ b/src/main/java/net/identio/server/service/orchestration/model/OrchestrationErrorStatus.java @@ -27,5 +27,5 @@ public class OrchestrationErrorStatus { public static final String AUTH_METHOD_UNKNOWN = "auth.method.unknown"; public static final String AUTH_METHOD_NOT_ALLOWED = "auth.method.not.allowed"; public static final String INVALID_TRANSACTION = "invalid.transaction"; - public static final String INVALID_REQUEST = "invalid.request"; + public static final String INVALID_SCOPE = "invalid.scope"; } diff --git a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java index d81afd4..10e3999 100644 --- a/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java +++ b/src/main/java/net/identio/server/service/orchestration/model/RequestParsingInfo.java @@ -24,6 +24,7 @@ import net.identio.server.model.AuthorizationScope; import net.identio.server.model.ProtocolType; +import java.util.LinkedHashMap; import java.util.List; public class RequestParsingInfo { @@ -38,8 +39,9 @@ public class RequestParsingInfo { private List requestedAuthLevels; private String relayState; private String responseUrl; - private List requestedScopes; + private LinkedHashMap requestedScopes; private String responseType; + private boolean consentNeeded; public RequestParsingStatus getStatus() { return status; @@ -131,11 +133,11 @@ public RequestParsingInfo setResponseUrl(String responseUrl) { return this; } - public List getRequestedScopes() { + public LinkedHashMap getRequestedScopes() { return requestedScopes; } - public RequestParsingInfo setRequestedScopes(List requestedScopes) { + public RequestParsingInfo setRequestedScopes(LinkedHashMap requestedScopes) { this.requestedScopes = requestedScopes; return this; } @@ -144,7 +146,17 @@ public String getResponseType() { return responseType; } - public void setResponseType(String responseType) { + public RequestParsingInfo setResponseType(String responseType) { this.responseType = responseType; + return this; + } + + public boolean isConsentNeeded() { + return consentNeeded; + } + + public RequestParsingInfo setConsentNeeded(boolean consentNeeded) { + this.consentNeeded = consentNeeded; + return this; } } diff --git a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java index d73871f..9d0bf72 100644 --- a/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java +++ b/src/test/java/net/identio/server/tests/integ/oauth/OAuthImplicitFullCinematicTest.java @@ -25,6 +25,7 @@ import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import net.identio.server.boot.IdentioServerApplication; +import net.identio.server.model.AuthorizationScope; import net.identio.server.mvc.common.model.ApiResponseStatus; import net.identio.server.mvc.common.model.AuthMethodResponse; import net.identio.server.mvc.common.model.AuthSubmitRequest; @@ -32,6 +33,7 @@ import net.identio.server.mvc.oauth.model.ConsentContext; import net.identio.server.mvc.oauth.model.ConsentRequest; import net.identio.server.mvc.oauth.model.ConsentResponse; +import org.apache.http.auth.AUTH; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -46,7 +48,9 @@ import java.security.*; import java.security.interfaces.RSAKey; import java.util.Arrays; +import java.util.Comparator; import java.util.Enumeration; +import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -132,8 +136,16 @@ public void oAuthAuthorizeValidRequest() { ConsentContext consentContext = consentContextEntity.getBody(); assertEquals("Test Client", consentContext.getAudience()); - assertEquals(Arrays.asList("scope.test.1", "scope.test.2"), consentContext.getRequestedScopes()); - assertEquals("/logo/app/test", consentContext.getAudienceLogo()); + + List requestedScopes = consentContext.getRequestedScopes(); + requestedScopes.sort(Comparator.comparing(AuthorizationScope::getName)); + + assertTrue(consentContext.getRequestedScopes().size() == 2); + + assertEquals("scope.test.1", consentContext.getRequestedScopes().get(0).getName()); + assertEquals("Accéder à scope test 1", consentContext.getRequestedScopes().get(0).getDescription().get("fr")); + assertEquals("Access scope test 1", consentContext.getRequestedScopes().get(0).getDescription().get("en")); + assertEquals("scope.test.2", consentContext.getRequestedScopes().get(1).getName()); // Send the consent ConsentRequest consentRequest = new ConsentRequest().setApprovedScopes(Arrays.asList("scope.test.1", "scope.test.2")); @@ -147,12 +159,10 @@ public void oAuthAuthorizeValidRequest() { ConsentResponse consentResponse = consentResponseEntity.getBody(); assertEquals(true, consentResponse.isSuccess()); - assertTrue(consentResponse.getResponse().matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); + assertTrue(consentResponse.getResponseData().getUrl() + .matches("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=.*&state=1234")); // Parse and validate JWT - Pattern pattern = Pattern.compile("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=(.*)&state=1234"); - Matcher matcher = pattern.matcher(authSubmitResponse.getDestinationUrl()); - Algorithm algorithm = null; try { algorithm = Algorithm.RSA256(getPublicSigningKey()); @@ -167,12 +177,14 @@ public void oAuthAuthorizeValidRequest() { .withClaim("scope", "scope.test.1 scope.test.2") .build(); + Pattern pattern = Pattern.compile("^http://example.com/cb#expires_in=2400&token_type=Bearer&access_token=(.*)&state=1234"); + Matcher matcher = pattern.matcher(consentResponse.getResponseData().getUrl()); + if (matcher.find()) { verifier.verify(matcher.group(1)); } else { fail(); } - } private RSAKey getPublicSigningKey() throws Exception { diff --git a/src/test/resources/oauth-server-config/identio-config.yml b/src/test/resources/oauth-server-config/identio-config.yml index 38c6c9b..bf38307 100644 --- a/src/test/resources/oauth-server-config/identio-config.yml +++ b/src/test/resources/oauth-server-config/identio-config.yml @@ -18,6 +18,9 @@ authorizationConfiguration: - name: scope.test.1 authLevel: *medium expirationTime: 2400 + description: + fr: Accéder à scope test 1 + en: Access scope test 1 - name: scope.test.2 authLevel: *strong expirationTime: 3600 diff --git a/src/test/resources/oauth-server-config/oauth-clients.yml b/src/test/resources/oauth-server-config/oauth-clients.yml index c08c949..042f5cb 100644 --- a/src/test/resources/oauth-server-config/oauth-clients.yml +++ b/src/test/resources/oauth-server-config/oauth-clients.yml @@ -9,4 +9,4 @@ oAuthClients: - http://example.com/cb allowedGrants: - implicit - needConsent: true + consentNeeded: true From 4e1f3635609f4d6870719a4241cd154948ef46bb Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Wed, 30 Aug 2017 17:45:00 +0200 Subject: [PATCH 034/104] Beginning of implementation of consent ui --- .../mvc/oauth/model/ConsentRequest.java | 1 - .../transaction/TransactionService.java | 10 +-- ui/app/index.html | 3 + ui/app/scripts/app.js | 20 +++-- ui/app/scripts/controllers/authController.js | 85 ++++++++++--------- .../scripts/controllers/consentController.js | 68 +++++++++++++++ ui/app/scripts/services/consentService.js | 45 ++++++++++ ui/app/views/consent.html | 40 +++++++++ ui/app/views/error.html | 4 +- 9 files changed, 224 insertions(+), 52 deletions(-) create mode 100644 ui/app/scripts/controllers/consentController.js create mode 100644 ui/app/scripts/services/consentService.js create mode 100644 ui/app/views/consent.html diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java index 564e7b5..e99b2d3 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentRequest.java @@ -27,7 +27,6 @@ public class ConsentRequest { private List approvedScopes; - public List getApprovedScopes() { return approvedScopes; } diff --git a/src/main/java/net/identio/server/service/transaction/TransactionService.java b/src/main/java/net/identio/server/service/transaction/TransactionService.java index 131208c..2c370a0 100644 --- a/src/main/java/net/identio/server/service/transaction/TransactionService.java +++ b/src/main/java/net/identio/server/service/transaction/TransactionService.java @@ -95,17 +95,15 @@ public TransactionData getTransaction(String sessionId, String transactionId) th TransactionData transactionData = fetchTransaction(transactionId); if (transactionData.getTransactionId() == null) { - String message = "Could not find a valid transaction"; - LOG.error(message); - throw new WebSecurityException(message); + LOG.error("Could not find a valid transaction"); + throw new WebSecurityException("invalid.transaction"); } if (!sessionId.equals(transactionData.getUserSession().getId())) { removeTransactionData(transactionData); - String message = "Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"; - LOG.error(message); - throw new WebSecurityException(message); + LOG.error("Session ID in transaction doesn't match browser session ID. Possible session fixation attack ?"); + throw new WebSecurityException("invalid.transaction"); } LOG.debug("Security verification OK"); diff --git a/ui/app/index.html b/ui/app/index.html index 6c9807f..fef2dd9 100644 --- a/ui/app/index.html +++ b/ui/app/index.html @@ -47,10 +47,13 @@ + + + diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index e67a46e..edcb0b1 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -36,7 +36,11 @@ }).state('logout', { url : '/logout', templateUrl : 'views/logout.html', - }); + }).state('consent', { + url : '/consent', + templateUrl : 'views/consent.html', + controller: 'ConsentController as consent' + }); // ** I18N $translateProvider.translations('en', { @@ -53,7 +57,11 @@ SUBMIT: 'Submit', SUBMIT_IN_PROGRESS: 'Submit in progress...', SAML_SECTION_HEADER: 'Alternatively you can login with:', - ERROR: "An error occured", + ERROR: 'An error occured', + CONSENT_TITLE: 'Authorize application', + CONSENT_MESSAGE: '{{applicationName}} would like permission to access your account', + AUTHORIZE: 'Authorize', + AUTHORIZE_IN_PROGRESS: 'Please wait...', // Errors 'invalid.credentials': 'Invalid username or password', @@ -69,8 +77,6 @@ // UI IDENTIO_SIGN_IN: 'Identifiez-vous sur Ident.io', - 'unknown.client': 'L’application client est inconnue', - AUTHENTICATION_METHOD: 'Moyen d’authentification', USERNAME: 'Identifiant', PASSWORD: 'Mot de passe', @@ -80,7 +86,11 @@ SUBMIT: 'Connexion', SUBMIT_IN_PROGRESS: 'Connexion en cours...', SAML_SECTION_HEADER: 'Alternativement, vous pouvez vous identifier sur:', - ERROR: "Une erreur s’est produite", + ERROR: 'Une erreur s’est produite', + CONSENT_TITLE: 'Autorization d’une application', + CONSENT_MESSAGE: 'souhaite obtenir la permission d’accéder à votre compte', + AUTHORIZE: 'Autoriser', + AUTHORIZE_IN_PROGRESS: 'Patientez...', // Errors 'invalid.credentials': 'Identifiant ou mot de passe invalide', diff --git a/ui/app/scripts/controllers/authController.js b/ui/app/scripts/controllers/authController.js index 7220259..d2d0239 100644 --- a/ui/app/scripts/controllers/authController.js +++ b/ui/app/scripts/controllers/authController.js @@ -18,7 +18,6 @@ vm.submitInProgress = false; vm.methodChoiceEnabled = true; vm.password = null; - vm.state = 'AUTH'; vm.error = null; vm.errorMessage = null; vm.challengeType = null; @@ -42,6 +41,7 @@ AuthService.getAuthMethods($stateParams.transactionId).then( function(successResponse) { + vm.methods = []; vm.samlMethods = []; @@ -58,18 +58,20 @@ $state.go('auth.' + vm.methods[0].type); }, function(errorResponse) { $state.go('error', { - errorCode : errorResponse.errorCode + errorId : errorResponse.data.errorCode }); }); } // Update the state on a source change function updateMethod() { + $state.go('auth.' + vm.selectedItem.type); } // Submit Authentication function submit() { + vm.submitInProgress = true; AuthService.submitAuth($stateParams.transactionId, @@ -79,9 +81,9 @@ } function samlSpSubmit(methodName) { - AuthService - .submitSamlAuth($stateParams.transactionId, methodName) - .success( + + AuthService.submitSamlAuth($stateParams.transactionId, methodName) + .then( function(data) { // Trust destination url @@ -91,49 +93,56 @@ $rootScope.$broadcast('saml.submit.request', data); - }).error(errorHandler); + }, errorHandler); } function authSubmitSuccessHandler(response) { var data = response.data; - if (data.status === 'RESPONSE') { - - data.responseData.url = $sce - .trustAsResourceUrl(data.responseData.url); - - if (data.protocolType === 'SAML') { - $rootScope.$broadcast('saml.submit.response', data.responseData); - } - if (data.protocolType === 'OAUTH') { - $rootScope.$broadcast('oauth.submit.response', data.responseData); - } - - return; - } - - if (data.errorStatus != null) { - vm.error = true; - vm.errorMessage = data.errorStatus; - vm.submitInProgress = false; - vm.password = null; - } - - if (data.challengeType != null) { - vm.challengeType = data.challengeType; - vm.challengeValue = data.challengeValue; - vm.submitInProgress = false; - vm.methodChoiceEnabled = false; - vm.password = null; - vm.error = false; - $state.go('auth.challenge'); - } + switch (data.status) { + + case 'RESPONSE': + data.responseData.url = $sce + .trustAsResourceUrl(data.responseData.url); + + if (data.protocolType === 'SAML') { + $rootScope.$broadcast('saml.submit.response', data.responseData); + } + if (data.protocolType === 'OAUTH') { + $rootScope.$broadcast('oauth.submit.response', data.responseData); + } + + return; + + case 'ERROR': + vm.error = true; + vm.errorMessage = data.errorStatus; + vm.submitInProgress = false; + vm.password = null; + return; + + case 'CHALLENGE': + vm.challengeType = data.challengeType; + vm.challengeValue = data.challengeValue; + vm.submitInProgress = false; + vm.methodChoiceEnabled = false; + vm.password = null; + vm.error = false; + $state.go('auth.challenge'); + return; + + case 'CONSENT': + vm.submitInProgress = false; + $state.go('consent', {transactionId: $stateParams.transactionId}); + return; + + } } function errorHandler(response) { $state.go('error', { - errorCode : response.data.errorCode + errorId : response.data.errorCode }); } } diff --git a/ui/app/scripts/controllers/consentController.js b/ui/app/scripts/controllers/consentController.js new file mode 100644 index 0000000..d373133 --- /dev/null +++ b/ui/app/scripts/controllers/consentController.js @@ -0,0 +1,68 @@ +(function() { + 'use strict'; + + /** + * @ngdoc function + * @name identioUiApp.controller:ConsentController + * @description # ConsentController of the identioUiApp + */ + angular.module('identioUiApp').controller('ConsentController', ConsentController); + + ConsentController.$inject = [ '$state', '$stateParams', '$sce', '$rootScope', '$translate', 'ConsentService' ]; + + function ConsentController($state, $stateParams, $sce, $rootScope, $translate, ConsentService) { + + /* jshint validthis: true */ + var vm = this; + + vm.submitInProgress = false; + vm.scopes = null; + vm.audience = "test"; + + vm.submit = submit; + init(); + + // Request the list of authentication methods + function init() { + + var context = ConsentService.getConsentContext($stateParams.transactionId) + .then(consentContextHandler, errorHandler); + } + + function consentContextHandler(response) { + vm.audience = response.data.audience; + + vm.scopes = []; + for (var i = 0; i < response.data.requestedScopes.length; i++) { + + var test = {}; + test.audience = response.data.requestedScopes[i].name; + test.description = response.data.requestedScopes[i].description[$translate.use()]; + + vm.scopes.push(test); + } + } + + + // Submit consent + function submit() { + vm.submitInProgress = true; + + + + + } + + function consentSubmitSuccessHandler(response) { + + + + } + + function errorHandler(response) { + $state.go('error', { + errorId : response.data.errorCode + }); + } + } +})(); diff --git a/ui/app/scripts/services/consentService.js b/ui/app/scripts/services/consentService.js new file mode 100644 index 0000000..9f2e1a9 --- /dev/null +++ b/ui/app/scripts/services/consentService.js @@ -0,0 +1,45 @@ +(function() { + 'use strict'; + + angular.module('identioUiApp').factory('ConsentService', ConsentService); + + ConsentService.$inject = [ '$http' ]; + + function ConsentService($http) { + + var service = { + getConsentContext : getConsentContext, + submitConsent : submitConsent + }; + + return service; + + // // Service implementation + function getConsentContext(transactionId) { + + return $http({ + method : 'GET', + url : '/api/authz/consent', + headers : { + 'X-Transaction-ID' : transactionId + } + }); + } + + function submitConsent(transactionId, validatedScopes) { + + var data = { + validatedScopes : validatedScopes + }; + + return $http({ + method : 'POST', + url : '/api/authz/consent', + headers : { + 'X-Transaction-ID' : transactionId + }, + data : data + }); + } + } +})(); diff --git a/ui/app/views/consent.html b/ui/app/views/consent.html new file mode 100644 index 0000000..f1bc7ee --- /dev/null +++ b/ui/app/views/consent.html @@ -0,0 +1,40 @@ + +
+ +
+
+

+ +
+ +
+ + +
+ +
+

{{consent.audience}}

+
+ + +
+ +
+ + +
+
+
+ diff --git a/ui/app/views/error.html b/ui/app/views/error.html index 468fe96..da392d3 100644 --- a/ui/app/views/error.html +++ b/ui/app/views/error.html @@ -3,12 +3,12 @@
-

+

- +
From bcbf37e4689cf93ceffe49e1d343569a76f6b9bc Mon Sep 17 00:00:00 2001 From: Loeiz TANGUY Date: Thu, 31 Aug 2017 15:43:56 +0200 Subject: [PATCH 035/104] Finalized consent integration --- .../server/mvc/oauth/ConsentController.java | 7 ++++ .../server/mvc/oauth/OAuthController.java | 2 +- .../mvc/oauth/model/ConsentResponse.java | 10 ----- .../server/service/oauth/ConsentService.java | 41 +++++++++++++++---- .../server/service/oauth/OAuthService.java | 33 +++++++++++---- .../service/oauth/model/OAuthErrors.java | 4 ++ ui/app/scripts/app.js | 4 +- .../scripts/controllers/consentController.js | 26 ++++++++---- ui/app/scripts/directives/oauth-responder.js | 2 +- ui/app/scripts/services/consentService.js | 4 +- ui/app/views/consent.html | 14 ++++--- 11 files changed, 101 insertions(+), 46 deletions(-) diff --git a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java index e004c65..a8656ef 100644 --- a/src/main/java/net/identio/server/mvc/oauth/ConsentController.java +++ b/src/main/java/net/identio/server/mvc/oauth/ConsentController.java @@ -20,12 +20,14 @@ */ package net.identio.server.mvc.oauth; +import net.identio.server.mvc.common.model.ApiErrorResponse; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.mvc.oauth.model.ConsentContext; import net.identio.server.mvc.oauth.model.ConsentRequest; import net.identio.server.mvc.oauth.model.ConsentResponse; import net.identio.server.service.oauth.ConsentService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @RestController @@ -51,4 +53,9 @@ public ConsentResponse receiveConsent(@RequestBody ConsentRequest consentRequest return consentService.validateConsent(consentRequest, transactionId, sessionId); } + @ResponseStatus(HttpStatus.FORBIDDEN) + @ExceptionHandler(WebSecurityException.class) + public ApiErrorResponse handleWebSecurityException(WebSecurityException e) { + return new ApiErrorResponse(e.getMessage()); + } } diff --git a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java index 04f4021..9070047 100644 --- a/src/main/java/net/identio/server/mvc/oauth/OAuthController.java +++ b/src/main/java/net/identio/server/mvc/oauth/OAuthController.java @@ -82,7 +82,7 @@ public String authorizeRequest( return "redirect:" + result.getResponseData().getUrl(); case CONSENT: - return "redirect:/#!/consent/"; + return "redirect:/#!/consent/" + result.getTransactionId(); case ERROR: return "redirect:/#!/error/" + result.getErrorStatus(); diff --git a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java index 30a53d1..8215736 100644 --- a/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java +++ b/src/main/java/net/identio/server/mvc/oauth/model/ConsentResponse.java @@ -25,18 +25,8 @@ public class ConsentResponse { - private boolean success; private ResponseData response; - public boolean isSuccess() { - return success; - } - - public ConsentResponse setSuccess(boolean success) { - this.success = success; - return this; - } - public ResponseData getResponseData() { return response; } diff --git a/src/main/java/net/identio/server/service/oauth/ConsentService.java b/src/main/java/net/identio/server/service/oauth/ConsentService.java index fea11ff..83449f1 100644 --- a/src/main/java/net/identio/server/service/oauth/ConsentService.java +++ b/src/main/java/net/identio/server/service/oauth/ConsentService.java @@ -23,6 +23,9 @@ import net.identio.server.mvc.oauth.model.ConsentRequest; import net.identio.server.mvc.oauth.model.ConsentResponse; +import net.identio.server.service.authorization.AuthorizationService; +import net.identio.server.service.authorization.exceptions.NoScopeProvidedException; +import net.identio.server.service.authorization.exceptions.UnknownScopeException; import net.identio.server.service.orchestration.exceptions.WebSecurityException; import net.identio.server.model.AuthorizationScope; import net.identio.server.service.orchestration.model.OrchestrationErrorStatus; @@ -48,6 +51,9 @@ public class ConsentService { @Autowired private OAuthService oAuthService; + @Autowired + private AuthorizationService authorizationService; + public ConsentContext getConsentContext(String transactionId, String sessionId) throws WebSecurityException { @@ -61,25 +67,42 @@ public ConsentContext getConsentContext(String transactionId, String sessionId) return new ConsentContext().setRequestedScopes(authorizedScopes) .setAudience(transactionData.getRequestParsingInfo().getSourceApplicationName()); - } public ConsentResponse validateConsent(ConsentRequest consentRequest, String transactionId, String sessionId) throws WebSecurityException { TransactionData transactionData = getTransactionData(transactionId, sessionId); - // Check that each validated scope is in the requested scopes - for (String scopeName : consentRequest.getApprovedScopes()) { - if (!transactionData.getRequestParsingInfo().getRequestedScopes().containsKey(scopeName)) { - throw new WebSecurityException(OrchestrationErrorStatus.INVALID_SCOPE); + ConsentResponse response = new ConsentResponse(); + + if (consentRequest == null || consentRequest.getApprovedScopes() == null || consentRequest.getApprovedScopes().size() == 0) { + + response.setResponseData( + oAuthService.generateErrorResponse(transactionData.getRequestParsingInfo(), false) + ); + } else { + // Check that each validated scope is in the requested scopes + for (String scopeName : consentRequest.getApprovedScopes()) { + if (!transactionData.getRequestParsingInfo().getRequestedScopes().containsKey(scopeName)) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_SCOPE); + } } - } - return new ConsentResponse().setSuccess(true) - .setResponseData( + try { + response.setResponseData( oAuthService.generateSuccessResponse(transactionData.getRequestParsingInfo(), - transactionData.getUserSession()) + transactionData.getUserSession(), authorizationService.getScopes(consentRequest.getApprovedScopes())) ); + } catch (UnknownScopeException | NoScopeProvidedException e) { + transactionService.removeTransactionData(transactionData); + throw new WebSecurityException(OrchestrationErrorStatus.INVALID_SCOPE); + } + } + + transactionService.removeTransactionData(transactionData); + + return response; } private TransactionData getTransactionData(String transactionId, String sessionId) throws WebSecurityException { diff --git a/src/main/java/net/identio/server/service/oauth/OAuthService.java b/src/main/java/net/identio/server/service/oauth/OAuthService.java index 037f0e3..0ec4aa8 100644 --- a/src/main/java/net/identio/server/service/oauth/OAuthService.java +++ b/src/main/java/net/identio/server/service/oauth/OAuthService.java @@ -152,17 +152,24 @@ public RequestParsingInfo validateAuthentRequest(OAuthInboundRequest request) { return result; } - public ResponseData generateSuccessResponse(RequestParsingInfo result, UserSession userSession) { + public ResponseData generateSuccessResponse(RequestParsingInfo requestParsingInfo, UserSession userSession) { + + return generateSuccessResponse(requestParsingInfo, userSession, requestParsingInfo.getRequestedScopes()); + } + + public ResponseData generateSuccessResponse(RequestParsingInfo requestParsingInfo, UserSession userSession, + LinkedHashMap approvedScopes) { StringBuilder responseBuilder = new StringBuilder(); - responseBuilder.append(result.getResponseUrl()).append("#expires_in="); + responseBuilder.append(requestParsingInfo.getResponseUrl()).append("#expires_in="); // Determine expiration time of the authorization and scope string int expirationTime = -1; + StringBuilder scopeBuilder = new StringBuilder(); - for (AuthorizationScope scope : result.getRequestedScopes().values()) { + for (AuthorizationScope scope : approvedScopes.values()) { int scopeExpirationTime = scope.getExpirationTime() != 0 ? scope.getExpirationTime() : 3600; @@ -177,32 +184,41 @@ public ResponseData generateSuccessResponse(RequestParsingInfo result, UserSessi scopeBuilder.deleteCharAt(scopeBuilder.length() - 1); // delete last comma - if (result.getResponseType().equals(OAuthResponseType.TOKEN)) { + if (requestParsingInfo.getResponseType().equals(OAuthResponseType.TOKEN)) { responseBuilder.append("&token_type=Bearer&access_token="); DateTime now = new DateTime(DateTimeZone.UTC); String accessToken = JWT.create().withIssuer(configurationService.getPublicFqdn()) .withExpiresAt(now.plusSeconds(expirationTime).toDate()).withIssuedAt(now.toDate()) - .withSubject(userSession.getUserId()).withAudience(result.getSourceApplicationName()) + .withSubject(userSession.getUserId()).withAudience(requestParsingInfo.getSourceApplicationName()) .withJWTId(UUID.randomUUID().toString()).withClaim("scope", scopeBuilder.toString()) .sign(Algorithm.RSA256(signingKey)); responseBuilder.append(accessToken); } - if (result.getRelayState() != null) { - responseBuilder.append("&state=").append(result.getRelayState()); + if (requestParsingInfo.getRelayState() != null) { + responseBuilder.append("&state=").append(requestParsingInfo.getRelayState()); } return new ResponseData().setUrl(responseBuilder.toString()); + } public ResponseData generateErrorResponse(RequestParsingInfo result) { + return generateErrorResponse(result, true); + } + + public ResponseData generateErrorResponse(RequestParsingInfo result, boolean consentResult) { + + // Determine the type of error to send + String errorStatus = consentResult ? result.getErrorStatus() : OAuthErrors.ACCESS_DENIED; + StringBuilder responseBuilder = new StringBuilder(); - responseBuilder.append(result.getResponseUrl()).append("#error=").append(result.getErrorStatus()); + responseBuilder.append(result.getResponseUrl()).append("#error=").append(errorStatus); if (result.getRelayState() != null) { responseBuilder.append("&state=").append(result.getRelayState()); @@ -252,5 +268,4 @@ private boolean checkClientAuthorization(OAuthClient client, String responseType return true; } - } diff --git a/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java index 0eac589..8527da4 100644 --- a/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java +++ b/src/main/java/net/identio/server/service/oauth/model/OAuthErrors.java @@ -23,9 +23,13 @@ public class OAuthErrors { + // Fatal errors (not sent to client) public static final String UNKNOWN_CLIENT = "unknown.client"; public static final String UNKNOWN_REDIRECT_URI = "unknown.redirect.uri"; + + // Errors that are sent to the client public static final String RESPONSE_TYPE_NOT_SUPPORTED = "unsupported_response_type"; public static final String INVALID_SCOPE = "invalid_scope"; public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; + public static final String ACCESS_DENIED = "access_denied"; } diff --git a/ui/app/scripts/app.js b/ui/app/scripts/app.js index edcb0b1..7044a0e 100644 --- a/ui/app/scripts/app.js +++ b/ui/app/scripts/app.js @@ -37,7 +37,7 @@ url : '/logout', templateUrl : 'views/logout.html', }).state('consent', { - url : '/consent', + url : '/consent/:transactionId', templateUrl : 'views/consent.html', controller: 'ConsentController as consent' }); @@ -87,7 +87,7 @@ SUBMIT_IN_PROGRESS: 'Connexion en cours...', SAML_SECTION_HEADER: 'Alternativement, vous pouvez vous identifier sur:', ERROR: 'Une erreur s’est produite', - CONSENT_TITLE: 'Autorization d’une application', + CONSENT_TITLE: 'Autorisation d’une application', CONSENT_MESSAGE: 'souhaite obtenir la permission d’accéder à votre compte', AUTHORIZE: 'Autoriser', AUTHORIZE_IN_PROGRESS: 'Patientez...', diff --git a/ui/app/scripts/controllers/consentController.js b/ui/app/scripts/controllers/consentController.js index d373133..31c2b3b 100644 --- a/ui/app/scripts/controllers/consentController.js +++ b/ui/app/scripts/controllers/consentController.js @@ -25,8 +25,7 @@ // Request the list of authentication methods function init() { - var context = ConsentService.getConsentContext($stateParams.transactionId) - .then(consentContextHandler, errorHandler); + ConsentService.getConsentContext($stateParams.transactionId).then(consentContextHandler, errorHandler); } function consentContextHandler(response) { @@ -35,27 +34,40 @@ vm.scopes = []; for (var i = 0; i < response.data.requestedScopes.length; i++) { - var test = {}; - test.audience = response.data.requestedScopes[i].name; - test.description = response.data.requestedScopes[i].description[$translate.use()]; + var scope = {}; + scope.name = response.data.requestedScopes[i].name; + scope.description = response.data.requestedScopes[i].description[$translate.use()]; + scope.selected = true; - vm.scopes.push(test); + vm.scopes.push(scope); } } // Submit consent function submit() { - vm.submitInProgress = true; + vm.submitInProgress = true; + var approvedScopes = []; + for (var i = 0; i < vm.scopes.length; i++) { + if (vm.scopes[i].selected) approvedScopes.push(vm.scopes[i].name); + } + ConsentService.submitConsent($stateParams.transactionId, approvedScopes).then(consentSubmitSuccessHandler, errorHandler); } function consentSubmitSuccessHandler(response) { + vm.submitInProgress = false; + + var data = response.data; + + data.responseData.url = $sce + .trustAsResourceUrl(data.responseData.url); + $rootScope.$broadcast('oauth.submit.response', data.responseData); } diff --git a/ui/app/scripts/directives/oauth-responder.js b/ui/app/scripts/directives/oauth-responder.js index 035975b..9a3d078 100644 --- a/ui/app/scripts/directives/oauth-responder.js +++ b/ui/app/scripts/directives/oauth-responder.js @@ -12,7 +12,7 @@ angular.module('identioUiApp') scope: {}, link: function($scope, element, $attrs) { $scope.$on($attrs.event, function(event, data) { - $window.location.href = data.destinationUrl; + $window.location.href = data.url; }); } }; diff --git a/ui/app/scripts/services/consentService.js b/ui/app/scripts/services/consentService.js index 9f2e1a9..a02ee14 100644 --- a/ui/app/scripts/services/consentService.js +++ b/ui/app/scripts/services/consentService.js @@ -26,10 +26,10 @@ }); } - function submitConsent(transactionId, validatedScopes) { + function submitConsent(transactionId, approvedScopes) { var data = { - validatedScopes : validatedScopes + approvedScopes : approvedScopes }; return $http({ diff --git a/ui/app/views/consent.html b/ui/app/views/consent.html index f1bc7ee..8778674 100644 --- a/ui/app/views/consent.html +++ b/ui/app/views/consent.html @@ -18,9 +18,15 @@