SAML20 FIXED

SAML20 FIXED
This commit is contained in:
shimingxy 2020-03-01 09:56:12 +08:00
parent ac9e2dd7ba
commit fba86d2577
14 changed files with 161 additions and 237 deletions

View File

@ -68,6 +68,10 @@ public class BasicAuthentication implements Authentication{
return j_username; return j_username;
} }
public String getUsername() {
return j_username;
}
public void setJ_username(String j_username) { public void setJ_username(String j_username) {
this.j_username = j_username; this.j_username = j_username;
} }
@ -83,6 +87,9 @@ public class BasicAuthentication implements Authentication{
public String getJ_sessionid() { public String getJ_sessionid() {
return j_sessionid; return j_sessionid;
} }
public String getSessionid() {
return j_sessionid;
}
public void setJ_sessionid(String j_sessionid) { public void setJ_sessionid(String j_sessionid) {
this.j_sessionid = j_sessionid; this.j_sessionid = j_sessionid;

View File

@ -69,8 +69,9 @@ public class SignatureSecurityPolicyRule implements InitializingBean, SecurityP
} }
SignableSAMLObject samlMessage = (SignableSAMLObject) messageContext.getInboundMessage(); SignableSAMLObject samlMessage = (SignableSAMLObject) messageContext.getInboundMessage();
//TODO:POST NEED Signed,but some is not
if( !samlMessage.isSigned()) { if( !samlMessage.isSigned()) {
logger.debug("evaluating signature POST NEED Signed,but some is not.");
throw new SecurityPolicyException("InboundMessage was not signed."); throw new SecurityPolicyException("InboundMessage was not signed.");
} }

View File

@ -22,7 +22,7 @@ public class AuthnRequestGenerator {
this.timeService = timeService; this.timeService = timeService;
this.idService = idService; this.idService = idService;
issuerGenerator = new IssuerGenerator(issuingEntityName); issuerGenerator = new IssuerGenerator(this.issuingEntityName);
} }
public AuthnRequest generateAuthnRequest(String destination, String responseLocation) { public AuthnRequest generateAuthnRequest(String destination, String responseLocation) {

View File

@ -86,11 +86,11 @@ public class MetadataEndpoint {
IDPSSODescriptor descriptor = metadataGenerator.buildIDPSSODescriptor(); IDPSSODescriptor descriptor = metadataGenerator.buildIDPSSODescriptor();
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,null)); descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/authz/saml20/"+appId,null));
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI)); descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/authz/saml20/"+appId,SAMLConstants.SAML2_REDIRECT_BINDING_URI));
descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/saml/v20/authz/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI)); descriptor.getSingleSignOnServices().add(metadataGenerator.getSingleSignOnService(WebContext.getHttpContextPath()+"/authz/saml20/"+appId,SAMLConstants.SAML2_POST_SIMPLE_SIGN_BINDING_URI));
descriptor.getSingleLogoutServices().add(metadataGenerator.getSingleLogoutService(WebContext.getHttpContextPath()+"/logout",null)); descriptor.getSingleLogoutServices().add(metadataGenerator.getSingleLogoutService(WebContext.getHttpContextPath()+"/logout",null));

View File

@ -1,19 +1,15 @@
package org.maxkey.authz.saml20.provider.endpoint; package org.maxkey.authz.saml20.provider.endpoint;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime;
import org.maxkey.authn.BasicAuthentication;
import org.maxkey.authz.saml.common.AuthnRequestInfo; import org.maxkey.authz.saml.common.AuthnRequestInfo;
import org.maxkey.authz.saml.common.EndpointGenerator; import org.maxkey.authz.saml.common.EndpointGenerator;
import org.maxkey.authz.saml20.binding.BindingAdapter; import org.maxkey.authz.saml20.binding.BindingAdapter;
import org.maxkey.authz.saml20.provider.xml.AuthnResponseGenerator; import org.maxkey.authz.saml20.provider.xml.AuthnResponseGenerator;
import org.maxkey.domain.apps.AppsSAML20Details; import org.maxkey.domain.apps.AppsSAML20Details;
import org.maxkey.web.WebContext;
import org.opensaml.saml2.core.Response; import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.metadata.Endpoint; import org.opensaml.saml2.metadata.Endpoint;
import org.opensaml.ws.message.encoder.MessageEncodingException; import org.opensaml.ws.message.encoder.MessageEncodingException;
@ -21,9 +17,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.ModelAndView;
@ -59,34 +52,13 @@ public class AssertionEndpoint {
logger.debug("AuthnRequestInfo: {}", authnRequestInfo); logger.debug("AuthnRequestInfo: {}", authnRequestInfo);
ArrayList<GrantedAuthority> grantedAuthority = new ArrayList<GrantedAuthority>();
grantedAuthority.add(new SimpleGrantedAuthority("ROLE_USER"));
UsernamePasswordAuthenticationToken authToken = (UsernamePasswordAuthenticationToken)WebContext.getAuthentication();
for(GrantedAuthority anthGrantedAuthority: authToken.getAuthorities()){
grantedAuthority.add(anthGrantedAuthority);
}
//TODO:
//String userName ="shimingxy@qq.com";
String userName =((BasicAuthentication )authToken.getPrincipal()).getJ_username();
//aly
//String userName ="admin@1729982683323703.onaliyun.com";
DateTime authnInstant = new DateTime(request.getSession().getCreationTime());
String remoteAddress=WebContext.getRequestIpAddress(request);
HashMap <String,String>attributeMap=new HashMap<String,String>(); HashMap <String,String>attributeMap=new HashMap<String,String>();
//saml20Details //saml20Details
Response authResponse = authnResponseGenerator.generateAuthnResponse( Response authResponse = authnResponseGenerator.generateAuthnResponse(
saml20Details, saml20Details,
authnRequestInfo, authnRequestInfo,
userName,
remoteAddress,
authnInstant,
grantedAuthority,
attributeMap, attributeMap,
bindingAdapter.getSigningCredential(), bindingAdapter);
bindingAdapter.getSpSigningCredential());
Endpoint endpoint = endpointGenerator.generateEndpoint(saml20Details.getSpAcsUrl()); Endpoint endpoint = endpointGenerator.generateEndpoint(saml20Details.getSpAcsUrl());

View File

@ -62,6 +62,7 @@ public class SingleSignOnEndpoint {
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
@PathVariable("appid") String appId)throws Exception { @PathVariable("appid") String appId)throws Exception {
logger.debug("SAML Authorize Redirect do POST , app id is "+appId);
return extractSAMLRequest(extractPostBindingAdapter,appId,request); return extractSAMLRequest(extractPostBindingAdapter,appId,request);
} }
@ -70,7 +71,7 @@ public class SingleSignOnEndpoint {
HttpServletRequest request, HttpServletRequest request,
HttpServletResponse response, HttpServletResponse response,
@PathVariable("appid") String appId)throws Exception { @PathVariable("appid") String appId)throws Exception {
logger.debug("SAML Authorize Redirect do GET , app id is "+appId);
return extractSAMLRequest(extractRedirectBindingAdapter,appId,request); return extractSAMLRequest(extractRedirectBindingAdapter,appId,request);
} }

View File

@ -1,12 +1,15 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import java.util.Collection; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.maxkey.authz.saml.service.IDService; import org.maxkey.authz.saml.service.IDService;
import org.maxkey.authz.saml.service.TimeService; import org.maxkey.authz.saml.service.TimeService;
import org.maxkey.authz.saml20.binding.BindingAdapter;
import org.maxkey.authz.saml20.xml.IssuerGenerator; import org.maxkey.authz.saml20.xml.IssuerGenerator;
import org.maxkey.domain.apps.AppsSAML20Details;
import org.maxkey.web.WebContext;
import org.opensaml.Configuration; import org.opensaml.Configuration;
import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.AttributeStatement; import org.opensaml.saml2.core.AttributeStatement;
@ -15,12 +18,21 @@ import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.Subject; import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.impl.AssertionBuilder; import org.opensaml.saml2.core.impl.AssertionBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory; import org.opensaml.xml.security.BasicSecurityConfiguration;
import org.opensaml.xml.security.credential.BasicCredential;
import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureConstants;
import org.opensaml.xml.signature.Signer;
import org.opensaml.xml.signature.impl.SignatureBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
public class AssertionGenerator { public class AssertionGenerator {
private final static Logger logger = LoggerFactory.getLogger(AssertionGenerator.class);
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
private final IssuerGenerator issuerGenerator; private final IssuerGenerator issuerGenerator;
private final SubjectGenerator subjectGenerator; private final SubjectGenerator subjectGenerator;
@ -44,42 +56,75 @@ public class AssertionGenerator {
} }
public Assertion generateAssertion( public Assertion generateAssertion(
AppsSAML20Details saml20Details,
BindingAdapter bindingAdapter,
String assertionConsumerURL, String assertionConsumerURL,
String nameIdValue,
String inResponseTo, String inResponseTo,
String audienceUrl, String audienceUrl,
int validInSeconds, int validInSeconds,
Collection<GrantedAuthority> authorities, HashMap<String,String>attributeMap
HashMap<String,String>attributeMap, ) {
String clientAddress,
DateTime authnInstant) {
AssertionBuilder assertionBuilder = (AssertionBuilder) builderFactory.getBuilder(Assertion.DEFAULT_ELEMENT_NAME);
Assertion assertion = assertionBuilder.buildObject();
Assertion assertion = new AssertionBuilder().buildObject();;
//Subject
Subject subject = subjectGenerator.generateSubject( Subject subject = subjectGenerator.generateSubject(
assertionConsumerURL, assertionConsumerURL,
nameIdValue,
inResponseTo, inResponseTo,
validInSeconds, validInSeconds);
clientAddress);
assertion.setSubject(subject); assertion.setSubject(subject);
//issuer
Issuer issuer = issuerGenerator.generateIssuer(); Issuer issuer = issuerGenerator.generateIssuer();
assertion.setIssuer(issuer); assertion.setIssuer(issuer);
//AuthnStatements
DateTime authnInstant = new DateTime(WebContext.getSession().getCreationTime());
AuthnStatement authnStatement = authnStatementGenerator.generateAuthnStatement(authnInstant); AuthnStatement authnStatement = authnStatementGenerator.generateAuthnStatement(authnInstant);
assertion.getAuthnStatements().add(authnStatement); assertion.getAuthnStatements().add(authnStatement);
//AttributeStatements
AttributeStatement attributeStatement =attributeStatementGenerator.generateAttributeStatement(authorities, attributeMap); ArrayList<GrantedAuthority> grantedAuthoritys = new ArrayList<GrantedAuthority>();
grantedAuthoritys.add(new SimpleGrantedAuthority("ROLE_USER"));
for(GrantedAuthority anthGrantedAuthority: ((UsernamePasswordAuthenticationToken)WebContext.getAuthentication()).getAuthorities()){
grantedAuthoritys.add(anthGrantedAuthority);
}
AttributeStatement attributeStatement =attributeStatementGenerator.generateAttributeStatement(
saml20Details, grantedAuthoritys,attributeMap);
assertion.getAttributeStatements().add(attributeStatement); assertion.getAttributeStatements().add(attributeStatement);
//ID
assertion.setID(idService.generateID()); assertion.setID(idService.generateID());
//IssueInstant
assertion.setIssueInstant(timeService.getCurrentDateTime()); assertion.setIssueInstant(timeService.getCurrentDateTime());
//Conditions
Conditions conditions = conditionsGenerator.generateConditions(audienceUrl,validInSeconds); Conditions conditions = conditionsGenerator.generateConditions(audienceUrl,validInSeconds);
assertion.setConditions(conditions); assertion.setConditions(conditions);
//sign Assertion
try{
BasicCredential basicCredential = new BasicCredential();
basicCredential.setPrivateKey(bindingAdapter.getSigningCredential().getPrivateKey());
Signature signature = new SignatureBuilder().buildObject();
signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
signature.setSigningCredential(basicCredential);
KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration
.getGlobalSecurityConfiguration()
.getKeyInfoGeneratorManager().getDefaultManager()
.getFactory(bindingAdapter.getSigningCredential());
signature.setKeyInfo(keyInfoGeneratorFactory.newInstance().generate(bindingAdapter.getSigningCredential()));
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
assertion.setSignature(signature);
Configuration.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
Signer.signObject(signature);
logger.debug("assertion.isSigned "+assertion.isSigned());
}catch (Exception e) {
e.printStackTrace();
logger.info("Unable to Signer assertion ",e);
}
return assertion; return assertion;
} }

View File

@ -1,16 +1,16 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import org.maxkey.authz.saml20.binding.BindingAdapter; import org.maxkey.constants.BOOLEAN;
import org.maxkey.domain.ExtraAttr; import org.maxkey.domain.ExtraAttr;
import org.maxkey.domain.ExtraAttrs; import org.maxkey.domain.ExtraAttrs;
import org.maxkey.domain.apps.AppsSAML20Details; import org.maxkey.domain.apps.AppsSAML20Details;
import org.maxkey.web.WebContext;
import org.opensaml.Configuration; import org.opensaml.Configuration;
import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement; import org.opensaml.saml2.core.AttributeStatement;
@ -29,40 +29,35 @@ public class AttributeStatementGenerator {
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory(); private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
public AttributeStatement generateAttributeStatement(Collection<GrantedAuthority> authorities) { public AttributeStatement generateAttributeStatement(AppsSAML20Details saml20Details,ArrayList<GrantedAuthority> grantedAuthoritys) {
return generateAttributeStatement(authorities, null); return generateAttributeStatement(saml20Details, grantedAuthoritys,null);
} }
public AttributeStatement generateAttributeStatement( public AttributeStatement generateAttributeStatement(
Collection<GrantedAuthority> authorities, AppsSAML20Details saml20Details,
ArrayList<GrantedAuthority> grantedAuthoritys,
HashMap<String,String>attributeMap) { HashMap<String,String>attributeMap) {
AttributeStatementBuilder attributeStatementBuilder = (AttributeStatementBuilder) builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME); AttributeStatementBuilder attributeStatementBuilder = (AttributeStatementBuilder) builderFactory.getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME);
AttributeStatement attributeStatement = attributeStatementBuilder.buildObject(); AttributeStatement attributeStatement = attributeStatementBuilder.buildObject();
if(null!=authorities){
Attribute attributeGrantedAuthority=builderGrantedAuthority(authorities); Attribute attributeGrantedAuthority=builderGrantedAuthority(grantedAuthoritys);
attributeStatement.getAttributes().add(attributeGrantedAuthority); attributeStatement.getAttributes().add(attributeGrantedAuthority);
}
if(null!=attributeMap){ if(null!=attributeMap){
Iterator<Entry<String, String>> iterator = attributeMap.entrySet().iterator(); Iterator<Entry<String, String>> iterator = attributeMap.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next(); Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();
String key = entry.getKey(); String key = entry.getKey();
String value = entry.getValue(); String value = entry.getValue();
Attribute attribute=builderAttribute(key,value,Attribute.BASIC); Attribute attribute=builderAttribute(key,value,Attribute.BASIC);
attributeStatement.getAttributes().add(attribute); attributeStatement.getAttributes().add(attribute);
} }
} }
BindingAdapter bindingAdapter = (BindingAdapter) WebContext.getSession().getAttribute("samlv20Adapter");
AppsSAML20Details saml20Details = bindingAdapter.getSaml20Details();
logger.debug("ExtendAttr "+saml20Details.getExtendAttr()); logger.debug("ExtendAttr "+saml20Details.getExtendAttr());
if(saml20Details.getIsExtendAttr()==1) { if(BOOLEAN.isTrue(saml20Details.getIsExtendAttr())) {
ExtraAttrs extraAttrs=new ExtraAttrs(saml20Details.getExtendAttr()); ExtraAttrs extraAttrs=new ExtraAttrs(saml20Details.getExtendAttr());
for(ExtraAttr extraAttr : extraAttrs.getExtraAttrs()) { for(ExtraAttr extraAttr : extraAttrs.getExtraAttrs()) {
logger.debug("Attribute : "+extraAttr.getAttr()+" , Vale : "+extraAttr.getValue()+" , Type : "+extraAttr.getType()); logger.debug("Attribute : "+extraAttr.getAttr()+" , Vale : "+extraAttr.getValue()+" , Type : "+extraAttr.getType());
@ -79,39 +74,36 @@ public class AttributeStatementGenerator {
attribute.setName(attributeName); attribute.setName(attributeName);
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic // urn:oasis:names:tc:SAML:2.0:attrname-format:basic
if(nameFormat==null || nameFormat.equals("")) {
nameFormat=Attribute.BASIC;
}
attribute.setNameFormat(nameFormat); attribute.setNameFormat(nameFormat);
if(value!=null) {
// Response/Assertion/AttributeStatement/Attribute/AttributeValue attribute.getAttributeValues().add(builderAttributeValue(value));
XSStringBuilder stringBuilder = (XSStringBuilder) builderFactory.getBuilder(XSString.TYPE_NAME); }
XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
stringValue.setValue(value);
attribute.getAttributeValues().add(stringValue);
return attribute; return attribute;
} }
public Attribute builderGrantedAuthority(Collection<GrantedAuthority> authorities){ public Attribute builderGrantedAuthority(Collection<GrantedAuthority> authorities){
// Response/Assertion/AttributeStatement/Attribute // Response/Assertion/AttributeStatement/Attribute
AttributeBuilder attributeBuilder = (AttributeBuilder) builderFactory.getBuilder(Attribute.DEFAULT_ELEMENT_NAME); Attribute attribute = builderAttribute("GrantedAuthority",null,null);
Attribute attribute = attributeBuilder.buildObject();
attribute.setName("GrantedAuthority");
// urn:oasis:names:tc:SAML:2.0:attrname-format:basic
attribute.setNameFormat(Attribute.BASIC);
for (GrantedAuthority grantedAuthority : authorities) { for (GrantedAuthority grantedAuthority : authorities) {
// this was convoluted to figure out // this was convoluted to figure out
// Response/Assertion/AttributeStatement/Attribute/AttributeValue // Response/Assertion/AttributeStatement/Attribute/AttributeValue
XSStringBuilder stringBuilder = (XSStringBuilder) Configuration.getBuilderFactory().getBuilder(XSString.TYPE_NAME); attribute.getAttributeValues().add(builderAttributeValue(grantedAuthority.getAuthority()));
XSString stringValue = stringBuilder.buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
stringValue.setValue(grantedAuthority.getAuthority());
attribute.getAttributeValues().add(stringValue);
} }
return attribute; return attribute;
} }
public XSString builderAttributeValue(String value) {
XSString xsStringValue = new XSStringBuilder().buildObject(AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
xsStringValue.setValue(value);
return xsStringValue;
}
} }

View File

@ -1,55 +1,35 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import org.joda.time.DateTime;
import org.maxkey.authz.saml.common.AuthnRequestInfo; import org.maxkey.authz.saml.common.AuthnRequestInfo;
import org.maxkey.authz.saml.service.IDService; import org.maxkey.authz.saml.service.IDService;
import org.maxkey.authz.saml.service.TimeService; import org.maxkey.authz.saml.service.TimeService;
import org.maxkey.authz.saml20.binding.BindingAdapter;
import org.maxkey.authz.saml20.xml.IssuerGenerator; import org.maxkey.authz.saml20.xml.IssuerGenerator;
import org.maxkey.constants.BOOLEAN; import org.maxkey.constants.BOOLEAN;
import org.maxkey.domain.apps.AppsSAML20Details; import org.maxkey.domain.apps.AppsSAML20Details;
import org.opensaml.Configuration; import org.opensaml.Configuration;
import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.EncryptedAssertion; import org.opensaml.saml2.core.EncryptedAssertion;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.Response; import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.impl.ResponseBuilder; import org.opensaml.saml2.core.impl.ResponseBuilder;
import org.opensaml.saml2.encryption.Encrypter; import org.opensaml.saml2.encryption.Encrypter;
import org.opensaml.saml2.encryption.Encrypter.KeyPlacement; import org.opensaml.saml2.encryption.Encrypter.KeyPlacement;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.encryption.EncryptionConstants; import org.opensaml.xml.encryption.EncryptionConstants;
import org.opensaml.xml.encryption.EncryptionException;
import org.opensaml.xml.encryption.EncryptionParameters; import org.opensaml.xml.encryption.EncryptionParameters;
import org.opensaml.xml.encryption.KeyEncryptionParameters; import org.opensaml.xml.encryption.KeyEncryptionParameters;
import org.opensaml.xml.io.Marshaller;
import org.opensaml.xml.io.MarshallerFactory;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.BasicSecurityConfiguration;
import org.opensaml.xml.security.credential.BasicCredential;
import org.opensaml.xml.security.credential.Credential;
import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory; import org.opensaml.xml.security.keyinfo.KeyInfoGeneratorFactory;
import org.opensaml.xml.signature.Signature;
import org.opensaml.xml.signature.SignatureConstants;
import org.opensaml.xml.signature.SignatureException;
import org.opensaml.xml.signature.Signer;
import org.opensaml.xml.signature.impl.SignatureBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
public class AuthnResponseGenerator { public class AuthnResponseGenerator {
private final static Logger logger = LoggerFactory.getLogger(AuthnResponseGenerator.class); private final static Logger logger = LoggerFactory.getLogger(AuthnResponseGenerator.class);
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
private String issuerName; private String issuerName;
private IDService idService; private IDService idService;
private TimeService timeService; private TimeService timeService;
private AssertionGenerator assertionGenerator; private AssertionGenerator assertionGenerator;
private IssuerGenerator issuerGenerator; private IssuerGenerator issuerGenerator;
private StatusGenerator statusGenerator; private StatusGenerator statusGenerator;
@ -58,113 +38,64 @@ public class AuthnResponseGenerator {
this.issuerName = issuerName; this.issuerName = issuerName;
this.idService = idService; this.idService = idService;
this.timeService = timeService; this.timeService = timeService;
issuerGenerator = new IssuerGenerator(issuerName); issuerGenerator = new IssuerGenerator(this.issuerName);
assertionGenerator = new AssertionGenerator(issuerName, timeService, idService); assertionGenerator = new AssertionGenerator(issuerName, timeService, idService);
statusGenerator = new StatusGenerator(); statusGenerator = new StatusGenerator();
} }
public Response generateAuthnResponse( AppsSAML20Details saml20Details, public Response generateAuthnResponse( AppsSAML20Details saml20Details,
AuthnRequestInfo authnRequestInfo, AuthnRequestInfo authnRequestInfo,
String nameIdValue,
String clientAddress,
DateTime authnInstant,
Collection<GrantedAuthority> authorities,
HashMap<String,String>attributeMap, HashMap<String,String>attributeMap,
Credential signingCredential, BindingAdapter bindingAdapter){
Credential spSigningCredential){
ResponseBuilder responseBuilder = (ResponseBuilder) builderFactory.getBuilder(Response.DEFAULT_ELEMENT_NAME);
Response authResponse = responseBuilder.buildObject();
int validInSeconds=Integer.parseInt(saml20Details.getValidityInterval());
String audienceUrl=saml20Details.getAudience();
String assertionConsumerURL=saml20Details.getSpAcsUrl();
String inResponseTo=authnRequestInfo.getAuthnRequestID();
Issuer responseIssuer = issuerGenerator.generateIssuer();
Response authResponse = new ResponseBuilder().buildObject();
//builder Assertion
Assertion assertion = assertionGenerator.generateAssertion( Assertion assertion = assertionGenerator.generateAssertion(
assertionConsumerURL, saml20Details,
nameIdValue, bindingAdapter,
inResponseTo, saml20Details.getSpAcsUrl(),
audienceUrl, authnRequestInfo.getAuthnRequestID(),
validInSeconds, saml20Details.getAudience(),
authorities, Integer.parseInt(saml20Details.getValidityInterval()),
attributeMap, attributeMap);
clientAddress,
authnInstant);
try{ //Encrypt
if(BOOLEAN.isTrue(saml20Details.getEncrypted())) {
logger.debug("authResponse.isSigned "+authResponse.isSigned()); logger.info("begin to encrypt assertion");
try {
//assertion.setSignature(newSignature);
if(BOOLEAN.isTrue(saml20Details.getEncrypted())) {
// Assume this contains a recipient's RSA public // Assume this contains a recipient's RSA public
logger.info("begin to encrypt assertion");
EncryptionParameters encryptionParameters = new EncryptionParameters(); EncryptionParameters encryptionParameters = new EncryptionParameters();
encryptionParameters.setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128); encryptionParameters.setAlgorithm(EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128);
logger.info("encryption assertion Algorithm : "+EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128); logger.info("encryption assertion Algorithm : "+EncryptionConstants.ALGO_ID_BLOCKCIPHER_AES128);
KeyEncryptionParameters keyEncryptionParameters = new KeyEncryptionParameters(); KeyEncryptionParameters keyEncryptionParameters = new KeyEncryptionParameters();
keyEncryptionParameters.setEncryptionCredential(spSigningCredential); keyEncryptionParameters.setEncryptionCredential(bindingAdapter.getSpSigningCredential());
// kekParams.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP); // kekParams.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSAOAEP);
keyEncryptionParameters.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15); keyEncryptionParameters.setAlgorithm(EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15);
logger.info("keyEncryption Algorithm : "+EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15); logger.info("keyEncryption Algorithm : "+EncryptionConstants.ALGO_ID_KEYTRANSPORT_RSA15);
KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration
.getGlobalSecurityConfiguration() .getGlobalSecurityConfiguration()
.getKeyInfoGeneratorManager().getDefaultManager() .getKeyInfoGeneratorManager().getDefaultManager()
.getFactory(spSigningCredential); .getFactory(bindingAdapter.getSpSigningCredential());
keyEncryptionParameters.setKeyInfoGenerator(keyInfoGeneratorFactory.newInstance()); keyEncryptionParameters.setKeyInfoGenerator(keyInfoGeneratorFactory.newInstance());
Encrypter encrypter = new Encrypter(encryptionParameters, keyEncryptionParameters); Encrypter encrypter = new Encrypter(encryptionParameters, keyEncryptionParameters);
encrypter.setKeyPlacement(KeyPlacement.PEER); encrypter.setKeyPlacement(KeyPlacement.PEER);
EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion); EncryptedAssertion encryptedAssertion = encrypter.encrypt(assertion);
authResponse.getEncryptedAssertions().add(encryptedAssertion); authResponse.getEncryptedAssertions().add(encryptedAssertion);
}catch(Exception e) {
logger.info("Unable to encrypt assertion .",e);
} }
}else {
SignatureBuilder signatureBuilder = (SignatureBuilder) builderFactory.getBuilder(Signature.DEFAULT_ELEMENT_NAME);
BasicCredential basicCredential = new BasicCredential();
basicCredential.setPrivateKey(signingCredential.getPrivateKey());
Signature signature = signatureBuilder.buildObject();
signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
signature.setSigningCredential(basicCredential);
KeyInfoGeneratorFactory keyInfoGeneratorFactory = Configuration
.getGlobalSecurityConfiguration()
.getKeyInfoGeneratorManager().getDefaultManager()
.getFactory(signingCredential);
signature.setKeyInfo(keyInfoGeneratorFactory.newInstance().generate(signingCredential));
BasicSecurityConfiguration config = (BasicSecurityConfiguration) Configuration.getGlobalSecurityConfiguration();
config.registerSignatureAlgorithmURI("RSA", SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256);
config.setSignatureReferenceDigestMethod(SignatureConstants.ALGO_ID_DIGEST_SHA256);
assertion.setSignature(signature);
Configuration.getMarshallerFactory().getMarshaller(assertion).marshall(assertion);
Signer.signObject(signature);
logger.debug("assertion.isSigned "+assertion.isSigned());;
authResponse.getAssertions().add(assertion); authResponse.getAssertions().add(assertion);
}
catch (EncryptionException e) {
logger.info("Unable to encrypt assertion .");
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} }
authResponse.setIssuer(responseIssuer); authResponse.setIssuer(issuerGenerator.generateIssuer());
authResponse.setID(idService.generateID()); authResponse.setID(idService.generateID());
authResponse.setIssueInstant(timeService.getCurrentDateTime()); authResponse.setIssueInstant(timeService.getCurrentDateTime());
authResponse.setInResponseTo(inResponseTo); authResponse.setInResponseTo(authnRequestInfo.getAuthnRequestID());
//authResponse.getAssertions().add(assertion); authResponse.setDestination(saml20Details.getSpAcsUrl());
authResponse.setDestination(assertionConsumerURL);
authResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI)); authResponse.setStatus(statusGenerator.generateStatus(StatusCode.SUCCESS_URI));
logger.debug("authResponse.isSigned "+authResponse.isSigned());
return authResponse; return authResponse;
} }

View File

@ -2,39 +2,33 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.saml2.core.AuthnContext; import org.opensaml.saml2.core.AuthnContext;
import org.opensaml.saml2.core.AuthnContextClassRef; import org.opensaml.saml2.core.AuthnContextClassRef;
import org.opensaml.saml2.core.AuthnStatement; import org.opensaml.saml2.core.AuthnStatement;
import org.opensaml.saml2.core.impl.AuthnContextBuilder; import org.opensaml.saml2.core.impl.AuthnContextBuilder;
import org.opensaml.saml2.core.impl.AuthnContextClassRefBuilder; import org.opensaml.saml2.core.impl.AuthnContextClassRefBuilder;
import org.opensaml.saml2.core.impl.AuthnStatementBuilder; import org.opensaml.saml2.core.impl.AuthnStatementBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AuthnStatementGenerator { public class AuthnStatementGenerator {
private final static Logger logger = LoggerFactory.getLogger(AuthnStatementGenerator.class);
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
public AuthnStatement generateAuthnStatement(DateTime authnInstant) { public AuthnStatement generateAuthnStatement(DateTime authnInstant) {
//Response/Assertion/AuthnStatement/AuthContext/AuthContextClassRef //Response/Assertion/AuthnStatement/AuthContext/AuthContextClassRef
AuthnContextClassRefBuilder authnContextClassRefBuilder = (AuthnContextClassRefBuilder) builderFactory.getBuilder(AuthnContextClassRef.DEFAULT_ELEMENT_NAME); AuthnContextClassRef authnContextClassRef = new AuthnContextClassRefBuilder().buildObject();
AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject();
//urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport //urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
authnContextClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX); authnContextClassRef.setAuthnContextClassRef(AuthnContext.PPT_AUTHN_CTX);
//Response/Assertion/AuthnStatement/AuthContext //Response/Assertion/AuthnStatement/AuthContext
AuthnContextBuilder authnContextBuilder = (AuthnContextBuilder)builderFactory.getBuilder(AuthnContext.DEFAULT_ELEMENT_NAME); AuthnContext authnContext = new AuthnContextBuilder().buildObject();
AuthnContext authnContext = authnContextBuilder.buildObject();
authnContext.setAuthnContextClassRef(authnContextClassRef); authnContext.setAuthnContextClassRef(authnContextClassRef);
//Response/Assertion/AuthnStatement //Response/Assertion/AuthnStatement
AuthnStatementBuilder authnStatementBuilder = (AuthnStatementBuilder) builderFactory.getBuilder(AuthnStatement.DEFAULT_ELEMENT_NAME); AuthnStatement authnStatement = new AuthnStatementBuilder().buildObject();
AuthnStatement authnStatement = authnStatementBuilder.buildObject();
authnStatement.setAuthnContext(authnContext); authnStatement.setAuthnContext(authnContext);
authnStatement.setAuthnInstant(authnInstant); authnStatement.setAuthnInstant(authnInstant);
logger.debug("generateAuthnStatement authnInstant "+authnInstant);
return authnStatement; return authnStatement;
} }

View File

@ -2,23 +2,20 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.saml2.core.Audience; import org.opensaml.saml2.core.Audience;
import org.opensaml.saml2.core.AudienceRestriction; import org.opensaml.saml2.core.AudienceRestriction;
import org.opensaml.saml2.core.Conditions; import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.impl.AudienceBuilder; import org.opensaml.saml2.core.impl.AudienceBuilder;
import org.opensaml.saml2.core.impl.AudienceRestrictionBuilder; import org.opensaml.saml2.core.impl.AudienceRestrictionBuilder;
import org.opensaml.saml2.core.impl.ConditionsBuilder; import org.opensaml.saml2.core.impl.ConditionsBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConditionsGenerator { public class ConditionsGenerator {
private final static Logger logger = LoggerFactory.getLogger(ConditionsGenerator.class);
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
public Conditions generateConditions(String audienceUrl,int validInSeconds) { public Conditions generateConditions(String audienceUrl,int validInSeconds) {
ConditionsBuilder conditionsBuilder = (ConditionsBuilder) builderFactory.getBuilder(Conditions.DEFAULT_ELEMENT_NAME); Conditions conditions = new ConditionsBuilder().buildObject();
Conditions conditions = conditionsBuilder.buildObject();
conditions.setNotBefore(new DateTime()); conditions.setNotBefore(new DateTime());
conditions.setNotOnOrAfter(new DateTime().plus(validInSeconds*1000)); conditions.setNotOnOrAfter(new DateTime().plus(validInSeconds*1000));
@ -29,15 +26,13 @@ public class ConditionsGenerator {
} }
public AudienceRestriction builderAudienceRestriction(String audienceUrl){ public AudienceRestriction builderAudienceRestriction(String audienceUrl){
AudienceRestrictionBuilder audienceRestrictionBuilder = (AudienceRestrictionBuilder) builderFactory.getBuilder(AudienceRestriction.DEFAULT_ELEMENT_NAME); AudienceRestriction audienceRestriction = new AudienceRestrictionBuilder().buildObject();
AudienceRestriction audienceRestriction = audienceRestrictionBuilder.buildObject();
AudienceBuilder audienceBuilder = (AudienceBuilder) builderFactory.getBuilder(Audience.DEFAULT_ELEMENT_NAME); Audience audience = new AudienceBuilder().buildObject();
Audience audience = audienceBuilder.buildObject();
audience.setAudienceURI(audienceUrl); audience.setAudienceURI(audienceUrl);
audienceRestriction.getAudiences().add(audience); audienceRestriction.getAudiences().add(audience);
logger.debug("Audience URL "+audienceUrl);
return audienceRestriction; return audienceRestriction;
} }

View File

@ -1,20 +1,15 @@
package org.maxkey.authz.saml20.provider.xml; package org.maxkey.authz.saml20.provider.xml;
import org.opensaml.Configuration;
import org.opensaml.saml2.core.Status; import org.opensaml.saml2.core.Status;
import org.opensaml.saml2.core.StatusCode; import org.opensaml.saml2.core.StatusCode;
import org.opensaml.saml2.core.StatusMessage; import org.opensaml.saml2.core.StatusMessage;
import org.opensaml.saml2.core.impl.StatusBuilder; import org.opensaml.saml2.core.impl.StatusBuilder;
import org.opensaml.saml2.core.impl.StatusCodeBuilder; import org.opensaml.saml2.core.impl.StatusCodeBuilder;
import org.opensaml.saml2.core.impl.StatusMessageBuilder; import org.opensaml.saml2.core.impl.StatusMessageBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory;
public class StatusGenerator { public class StatusGenerator {
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
public Status generateStatus( String value ) { public Status generateStatus( String value ) {
Status status = builderStatus(); Status status = builderStatus();
@ -45,23 +40,19 @@ public class StatusGenerator {
} }
public Status builderStatus(){ public Status builderStatus(){
StatusBuilder builder = (StatusBuilder) builderFactory.getBuilder(Status.DEFAULT_ELEMENT_NAME); Status status = (Status) new StatusBuilder().buildObject();
Status status = (Status) builder.buildObject();
return status; return status;
} }
public StatusCode builderStatusCode(String value){ public StatusCode builderStatusCode(String value){
StatusCodeBuilder codeBuilder = (StatusCodeBuilder) builderFactory.getBuilder(StatusCode.DEFAULT_ELEMENT_NAME); StatusCode statusCode = (StatusCode) new StatusCodeBuilder().buildObject();
StatusCode statusCode = (StatusCode) codeBuilder.buildObject();
statusCode.setValue(value); statusCode.setValue(value);
return statusCode; return statusCode;
} }
public StatusMessage builderStatusMessage(String message){ public StatusMessage builderStatusMessage(String message){
StatusMessageBuilder statusMessageBuilder = (StatusMessageBuilder) builderFactory.getBuilder(StatusMessage.DEFAULT_ELEMENT_NAME); StatusMessage statusMessage = new StatusMessageBuilder().buildObject();
StatusMessage statusMessage = statusMessageBuilder.buildObject();
statusMessage.setMessage(message); statusMessage.setMessage(message);

View File

@ -3,6 +3,7 @@ package org.maxkey.authz.saml20.provider.xml;
import org.maxkey.authz.saml.service.TimeService; import org.maxkey.authz.saml.service.TimeService;
import org.maxkey.web.WebContext;
import org.opensaml.saml2.core.NameID; import org.opensaml.saml2.core.NameID;
import org.opensaml.saml2.core.NameIDType; import org.opensaml.saml2.core.NameIDType;
import org.opensaml.saml2.core.Subject; import org.opensaml.saml2.core.Subject;
@ -25,14 +26,14 @@ public class SubjectGenerator {
public Subject generateSubject( public Subject generateSubject(
String assertionConsumerURL, String assertionConsumerURL,
String nameIdValue,
String inResponseTo, String inResponseTo,
int validInSeconds, int validInSeconds) {
String clientAddress) {
String nameIdValue =WebContext.getUserInfo().getUsername();
NameID nameID =builderNameID(nameIdValue,assertionConsumerURL); NameID nameID =builderNameID(nameIdValue,assertionConsumerURL);
Subject subject =builderSubject(nameID); Subject subject =builderSubject(nameID);
String clientAddress=WebContext.getRequestIpAddress(WebContext.getRequest());
SubjectConfirmation subjectConfirmation =builderSubjectConfirmation( SubjectConfirmation subjectConfirmation =builderSubjectConfirmation(
assertionConsumerURL, assertionConsumerURL,
inResponseTo, inResponseTo,

View File

@ -1,16 +1,12 @@
package org.maxkey.authz.saml20.xml; package org.maxkey.authz.saml20.xml;
import org.opensaml.Configuration;
import org.opensaml.saml2.core.Issuer; import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.NameIDType; import org.opensaml.saml2.core.NameIDType;
import org.opensaml.saml2.core.impl.IssuerBuilder; import org.opensaml.saml2.core.impl.IssuerBuilder;
import org.opensaml.xml.XMLObjectBuilderFactory;
public class IssuerGenerator { public class IssuerGenerator {
private final XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
private final String issuerName; private final String issuerName;
public IssuerGenerator(String issuerName) { public IssuerGenerator(String issuerName) {
@ -19,14 +15,12 @@ public class IssuerGenerator {
public Issuer generateIssuer() { public Issuer generateIssuer() {
///Issuer ///Issuer
IssuerBuilder issuerBuilder = (IssuerBuilder) builderFactory.getBuilder(Issuer.DEFAULT_ELEMENT_NAME); Issuer issuer = new IssuerBuilder().buildObject();
Issuer issuer = issuerBuilder.buildObject();
issuer.setValue(issuerName); issuer.setValue(issuerName);
issuer.setFormat(NameIDType.ENTITY); issuer.setFormat(NameIDType.ENTITY);
return issuer; return issuer;
} }
} }