Could any one please give me a link of a good tutorial that could give me an idea how i could build a XACMLObject using openSAML2 api from the policie file ?
Thanks
I haven't use OpenSAML library for this purpose. But I have used for some other purpose which involved XACML requests and responses. Following may help you to get an idea. It is creating a XACMLRequest from a String.
private String extractXACMLRequest(String decisionQuery) throws Exception {
RequestType xacmlRequest = null;
doBootstrap();
String queryString = null;
XACMLAuthzDecisionQueryType xacmlAuthzDecisionQuery;
try {
xacmlAuthzDecisionQuery = (XACMLAuthzDecisionQueryType) unmarshall(decisionQuery);
//Access the XACML request only if Issuer and the Signature are valid.
if (validateIssuer(xacmlAuthzDecisionQuery.getIssuer())) {
if (validateSignature(xacmlAuthzDecisionQuery.getSignature())) {
xacmlRequest = xacmlAuthzDecisionQuery.getRequest();
} else {
log.debug("The submitted signature is not valid!");
}
} else {
log.debug("The submitted issuer is not valid!");
}
if (xacmlRequest != null) {
queryString = marshall(xacmlRequest);
queryString = queryString.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", "").replace("\n", "");
}
return queryString;
} catch (Exception e) {
log.error("Error unmarshalling the XACMLAuthzDecisionQuery.", e);
throw new Exception("Error unmarshalling the XACMLAuthzDecisionQuery.", e);
}
}
You want to use sunXACML or JAXB to marshall / unmarshall XACML policies not openSAML2.
Related
I have a web service accept two different interfaces(i.e. A and B) and there are some common fields which share same checking logic. However different error message have to be returned if the checking is failed and point out which field in the request body is invalid. Is there any way to reduce the code duplication for the checking logic.
Interface A may be accepting json as the request body,
{
"companyAClient":{
"id": 12345,
"name": "ABC Limited",
...
},
...
}
Interface B may be accepting xml as the request body with completly different structure compare to interface A
<MSG>
...
<MSG.BODY>
...
<COMPANY>
<CLIENT>
<ID>23456</ID>
<NAME>XYZ Limited</NAME>
...
</CLIENT>
...
</COMPANY>
...
</MSG.BODY>
</MSG>
private checkInterfaceA(String clientId, String clientName, other variables...) {
Long id;
try {
id = Long.parse(clientId);
} catch (Exception e) {
throw new InterfaceException("[EOS_E01] 'companyAClient.id' is empty.");
}
if(*clientId not exist in DB*) {
throw new InterfaceException("[EOS_E02] 'companyAClient.id' not match with DB records.");
}
if(*clientName.toUpperCase() not found in DB*) {
throw new InterfaceException("[EOS_E03] 'companyAClient.name' not match with DB records.");
}
Other checking...
}
private checkInterfaceB(String clientId, String clientName, other variables...) {
Long id;
try {
id = Long.parse(clientId);
} catch (Exception e) {
throw new InterfaceException("[E_XML_001] Parse Client ID error. Please check '/MSG/MSG.BODY/COMPANY/CLIENT/ID'.");
}
if(*clientId not exist in DB*) {
throw new InterfaceException("[E_XML_002] Client ID not found error. Please check '/MSG/MSG.BODY/COMPANY/CLIENT/ID'");
}
if(*clientName.toUpperCase() not found in DB*) {
throw new InterfaceException("[E_XML_003] Client name not found error. Please check '/MSG/MSG.BODY/COMPANY/CLIENT/NAME'");
}
Other checking...
}
You could make a method where you pass the text in.
private checkInterface0(String clientId, String msgTemplate) {
Long id;
try {
id = Long.parse(clientId);
} catch (Exception e) {
throw new InterfaceException(msgTemplate);
}
if(*clientId not exist in DB*) {
throw new InterfaceException(msgTemplate);
}
}
You might want to treat the template as either a filler (throw new InterfaceException("Parse ID error in " + template);) or by using string.format: throw new InterfaceException(String.format(template, "Parse ID error"). The parameter would be something like "%s in interface A".
I am new RESTful web Services and after going through some documentation I am in a state to invoke a web service. It looks like I am receiving a 200 status back from the service producer when I look at the response object but I am also getting javax.xml.bind.UnmarshallException. I get this exception when the code reaches to read the entity. I am a little lost as I am not sure what to do or what to look at in order to resolve this error.
XML Representation of Object
#XmlRootElement( name = "Somethig", namespace = "http://respone.something.com" )
#ReleaseInfo( version = "v4", description = "Response for Validate Email
Service" )
public class ThirdPartyValidateEMailAddressResponse extends BaseResponse {
private String emailAddressProvided;
private String emailAddressReturned;
private String mailboxName;
private String domainName;
private String topLevelDomain;
private String topLevelDomainDesc;
private boolean syntaxCorrected;
private boolean caseStandardized;
private boolean domainNameUpdated;
Client Code:
public ValidateEMailAddressServiceResponse validateEMailAddress( ValidateEMailAddressServiceRequest request ) throws Exception {
WebTarget service = config.createWebResource(request.getServiceURL());
ValidateEMailAddressServiceResponse resp = new ValidateEMailAddressServiceResponse();
service = service.path(SOMETHING).path(SOMETHING).path(SOMETHING).register(ThirdPartyValidateEmailResponseXMLReader.class);
ValidateEMailAddressServiceRequestParameter parameter = null;
parameter = request.getParameter(ValidateEMailAddressServiceRequestParameter.PARAMETERS.emailAddress.name());
if (parameter != null) {
service = service.queryParam(ValidateEMailAddressServiceRequestParameter.PARAMETERS.emailA
Invocation.Builder b = applyHeaders(service, request.getHeaders(), request.getHttpHeaders());
if(request.getAccepts() != null){
b = b.accept(request.getAccepts().value());
}
Response response = b.get(Response.class);
try {
resp = (ValidateEMailAddressServiceResponse) handleBaseResponse(resp, response);
// Managing business or error response
ThirdPartyValidateEMailAddressResponse thirdPartyResponse = null;
if (shouldProcessEntity(SOMETHING+ SOMETHING + SOMETHING, resp)) {
if (ContentType.XML.equals(request.getAccepts()) || ContentType.JSON.equals(request.getAccepts())) {
thirdPartyResponse = response.readEntity(ThirdPartyValidateEMailAddressResponse.class);
}
else {
throw new Exception("Invalid Content Type found while processing response");
}
}
else {
thirdPartyResponse = new ThirdPartyValidateEMailAddressResponse();
thirdPartyResponse.setMessages(createMessagesFromHTTPStatus(resp));
response.close();
}
}
catch (IOException e) {
throw new EISClientException("Exception in processing ValidateEMailAddress", e);
}
return resp;
}
Looks like it fails right here
thirdPartyResponse =
response.readEntity(ThirdPartyValidateEMailAddressResponse.class);
stack trace:
mig.eis.client.EISClientException: javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; Premature end of file.]
Please let me know if anything else is needed from my side to debug this issue.
Thanks
I wrote some java code using javax.naming.directory to authenticate a user in AD using ldap, that code working fine as I'm expecting. But the same code i need to implement using Spring ldap api. Any one can help on these.
To Initialize
private void setDefaultInitialContext() throws Exception
{
LOG.debug("Setting default initail context");
try
{
this.moLdapEnv.put(JAVA_NAMING_FACTORY_INITIAL, COM_SUN_JNDI_LDAP_LDAP_CTX_FACTORY);
this.moLdapEnv.put(JAVA_NAMING_PROVIDER_URL, PropertiesReader.getLdapProperty(LDAP_URL) + ":" + PropertiesReader.getLdapProperty(LDAP_PORT));
this.moLdapEnv.put(JAVA_NAMING_SECURITY_AUTHENTICATION, PropertiesReader.getLdapProperty(LDAP_AUTHTYPE));
this.moLdapEnv.put(JAVA_NAMING_SECURITY_PRINCIPAL, PropertiesReader.getLdapProperty(LDAP_BIND_USER_DN));
this.moLdapEnv.put(JAVA_NAMING_SECURITY_CREDENTIALS, PropertiesReader.getLdapProperty(LDAP_PASSWORD));
this.moLdapContext = new InitialDirContext(this.moLdapEnv);
LOG.debug("Default initail context is set");
} catch (Exception exception)
{
LOG.error("An Exception occurred LdapDao setting default initial context :" + exception.getMessage(), exception);
throw exception;
}
}
Authenticate:
public Boolean authenticate(String asUsername, String asUserPassword) throws Exception
{
NamingEnumeration<SearchResult> results = null;
Boolean liAuthResult = Boolean.FALSE;
try
{
setDefaultInitialContext();
SearchControls controls = new SearchControls();
controls.setSearchScope(2);
results = this.moLdapContext.search(PropertiesReader.getLdapProperty(LDAP_SEARCH_BASE_DN),
"(&(objectclass=person)(sAMAccountName=" + asUsername + ")(memberOf=" + PropertiesReader.getLdapProperty(LDAP_GROUP_DN) + "))",
controls);
if (null != results && results.hasMore())
{
SearchResult searchResult = (SearchResult) results.next();
if (null != searchResult)
{
moAttributes = searchResult.getAttributes();
Attribute userDnAttr = moAttributes.get(DISTINGUISHED_NAME);
String userDn = (String) userDnAttr.get();
this.moLdapContext.close();
this.moLdapEnv.put(JAVA_NAMING_SECURITY_PRINCIPAL, userDn);
this.moLdapEnv.put(JAVA_NAMING_SECURITY_CREDENTIALS, asUserPassword);
this.moLdapEnv.put(COM_SUN_JNDI_LDAP_CONNECT_POOL, FALSE);
this.moLdapContext = new InitialDirContext(this.moLdapEnv);
liAuthResult = Boolean.TRUE;
}
LOG.debug("User Authenticated successfully");
}
} catch (NamingException exception)
{
throw exception;
} catch (Exception exception)
{
throw exception;
} finally
{
closeAllResources(results);
}
return liAuthResult;
}
There's a separate chapter on authentication in the Spring LDAP reference manual. If you have specific questions feel free to ask.
Please note that for authentication/authorization purposes you really should look into Spring Security (which in turn uses Spring LDAP under the covers).
I am currently working in a service where i have to use validation with service.We are getting the input from client through request class storing in the database using entity by repository,where we have to give the annotations and where we have to give the bindingresult parameters.While we calling the the service the validation have to take place.Here,I have attached the sample code.
this is the service class where i tried to implement the validation
public long create(#Valid Document document,BindingResult bindingResult,DocumentResourceRequest DocumentResourceRequest,
long agreementId) throws Exception {
// TODO Auto-generated method stub
logger.info("In DocumentServiceImpl createLoanDocument");
Document documentObject = new Document(new lend(
agreementId));
documentObject.setDocumentType(DocumentResourceRequest
.getDocumentType());
documentObject.setDocumentDetails(DocumentResourceRequest
.getDocumentDetails());
documentObject.setRemarks(DocumentResourceRequest.getRemarks());
documentObject.setDocumentStatus(DocumentResourceRequest
.getDocumentStatus());
documentObject.setCreatedBy(DocumentResourceRequest
.getCreatedBy());
documentObject.setCreatedOn(new Date());
try {
if(document != null)
{
document = loanDocumentRepo.saveAndFlush(documentObject);//DocumentRepository
}else(bindingResult.getAllErrors())//if getting errors
{
}
} catch (Exception e) {
throw new Exception("Error in persisting Document-->" + e);
}
return document.getId();
}
'
I have registered my app engine app with my Office 365 environment and the callback URL is working, I receive an SPAppToken.
I want to get an Access Token using this java class:
http://javadoc.google-oauth-java-client.googlecode.com/hg/1.12.0-beta/com/google/api/client/auth/oauth2/AuthorizationCodeTokenRequest.html
My question is which of the values below map to the values I found in the SPAppToken ?
The credentials in ClientAuthentication are the applicationId and applicationSecret I asume. The redirectURI is to get back to my app.
I think the GenericURL should be populated with https://accounts.accesscontrol.windows.net/tokens/OAuth/2
But the I keep getting: Error: invalid_request
ACS90019: Unable to determine the tenant identifier from the request.
Below is the code xx means a variable that I need to replace and further below the SPAppToken (decoded from base64)
try {TokenResponse response = new AuthorizationCodeTokenRequest(new NetHttpTransport(), new JacksonFactory(), new GenericUrl(**"https://server.example.com/token"**), **"SplxlOBeZQQYbYS6WxSbIA"**).setRedirectUri("https://client.example.com/rd") .setClientAuthentication(new BasicAuthentication(**"s6BhdRkqt3"**, **"7Fjfp0ZBr1KtDRbnfVdmIw"**)).execute();
System.out.println("Access token: " + response.getAccessToken());
} catch (TokenResponseException e) {
if (e.getDetails() != null) {
System.err.println("Error: " + e.getDetails().getError());
if (e.getDetails().getErrorDescription() != null) {
System.err.println(e.getDetails().getErrorDescription());
}
if (e.getDetails().getErrorUri() != null) {
System.err.println(e.getDetails().getErrorUri());
}
} else {
System.err.println(e.getMessage());
}
}
SPAppToken decoded:
{"typ":"JWT","alg":"HS256"}{"aud":"e9e91cd9-0d95-46b7-8a05-f614a683e35d/eog-fire-ice.appspot.com#19d9feae-ba24-4c9e-831c-3132f2ea3974","iss":"00000001-0000-0000-c000-000000000000#19d9feae-ba24-4c9e-831c-3132f2ea3974","nbf":1353777617,"exp":1353820817,"appctxsender":"00000003-0000-0ff1-ce00-000000000000#19d9feae-ba24-4c9e-831c-3132f2ea3974","appctx":"{\"CacheKey\":\"hwqDPFbKDL9mIYpbReWYHeez1uES77UqEsxwienRA9g=\",\"SecurityTokenServiceUri\":\"https://accounts.accesscontrol.windows.net/tokens/OAuth/2\"}","refreshtoken":"IAAAAAi52NL58kY1UUpnmUJ9TPO7BpDSd6NqQGHbdfAEnOgioNbG8AwTGgf-3HPSNrdDexk5UUA3QFox_sky4_uon0XmLl6EfpqsC6RTpiatjJxXzB7EFJrqsiYI98MULyCubxjR5UyQwFzLvEjljEom7XcEXB2YCCWJQQdSRvFU4xo4NIPoUObhyjTK58TaCipUU3D4EiLJRSlkbcm_Y3VrVd8GMoQ8kx6BmJjeaGKZsJXWb7UJ8YTg6L4-HOoAiU3MymJl3oBxv_9rvHDmKb4FJ7vrN8AhJYUqlr9rZxOtG_BVeUX05E-umfoUU4PL2Cj-p7u4YOPo6rqVahovwGwYPn-pZbPfIcTj3TzKZdIk7OLemdR_S8_v0gASEM1Y_KTHsoQ6k-uZaa3QGZN4icu-Jp6Jh4UTRZuomLtkLmg7VVZL6VKpXUVW7RjUopoSEffb5RVmMVNOkNV4_r5NT7pjL0pWAk-uipTF0qLAMzEfr5M9YKNgBlbRbvjlePFz6co5_uOyY8VbfJsIqGhTr1dvW6o","isbrowserhostedapp":"true"}R?????XE??j?2??pZ?????0jLk
----- new info 2012-26-11 ------
After changing the "code" field to contain the refresh token and using the aud entire value instead of just the applicationID I get this message:
ACS50001: The required field 'resource' is missing.
The question is: am I getting closer or not ?
I have also asked this question here: https://groups.google.com/d/topic/google-oauth-java-client/EZtlwDbY_wk/discussion
I modified the com.google.api.client.json.JSONParser.java and put this code in my servlet:
JsonWebSignature jws = JsonWebSignature.parse(new JacksonFactory(), req.getParameter("SPAppToken"));
JsonParser jsonParser = new JacksonFactory().createJsonParser(jws.getPayload().get("appctx").toString());
//Create my own AppTxc that extends GenericJSON
AppCtx appCtx = jsonParser.parse(AppCtx.class, new CustomizeJsonParser());
String appctxsender=jws.getPayload().get("appctxsender").toString();
String[] splitApptxSender = appctxsender.split("#");
//sharepointhost name is part of the resource field
String sharepointServerHostName = new URL(req.getParameter("SPHostUrl")).getHost();
// create the resource field
String resource = splitApptxSender[0]+"/"+sharepointServerHostName+"#"+splitApptxSender[1];
try {
AuthorizationCodeTokenRequest tokenRequest = new AuthorizationCodeTokenRequest(new NetHttpTransport(), new JacksonFactory(),
new GenericUrl(appCtx.getSecurityTokenServiceUri()), jws.getPayload().get("refreshtoken").toString());
tokenRequest.setRedirectUri("https://eog-fire-ice.appspot.com/callback4fireandice");
tokenRequest.setClientAuthentication(
new ClientParametersAuthentication(jws.getPayload().getAudience(), SharePointAppSecret));
tokenRequest.setGrantType("refresh_token");
tokenRequest.set("resource", resource);
tokenRequest.set("refresh_token", jws.getPayload().get("refreshtoken").toString());
TokenResponse response =tokenRequest.execute();
String accesstoken=response.getAccessToken();
} catch (TokenResponseException e) {
if (e.getDetails() != null) {
pw.println("Error: " + e.getDetails().getError());
if (e.getDetails().getErrorDescription() != null) {
pw.println(e.getDetails().getErrorDescription());
}
if (e.getDetails().getErrorUri() != null) {
pw.println(e.getDetails().getErrorUri());
}
} else {
pw.println(e.getMessage());
}
}
I am not sure if all information (like the redirectURL is necessary, but now I have got an accesstoken from Azure ACS.
Thanks to Nick Swan (lightningtools.com) for the initial help based on Ruby on Rails.
On of course thanks to Yaniv Inbar (https://plus.google.com/+YanivInbar/) for providing the google oauth java client library.
I had to raise a bug report though: http://code.google.com/p/google-oauth-java-client/issues/detail?id=62&q=Type%3DDefect&sort=priority&colspec=ID%20Milestone%20Summary