Error trying to access SmartCloud using OAuth - oauth

I'm trying to use the Social Business Toolkit to access SmartCloud using OAuth, but I'm getting this error. Using SmartCloudBasicEndpoint everything works fine.
[4/4/14 12:01:56:236 CEST] 00000038 SBTProxy I URL computed from SBTProxy is https://apps.na.collabserv.com/communities/service/atom/oauth/communities/all
[4/4/14 12:01:56:556 CEST] 00000038 E com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler _performOAuth1Dance Failed to get request token. requestUrl:https://apps.na.collabserv.com/manage/oauth/getRequestToken, authorizeUrl: https://apps.na.collabserv.com/manage/oauth/authorizeToken, accessUrl: https://apps.na.collabserv.com/manage/oauth/getAccessToken, callback: null, truncated key:a919....1b25, truncated secret:9054....687d. OAuth callback is empty, please check with your application vendor to ensure a callback is not required.
com.ibm.sbt.security.authentication.oauth.OAuthException: Internal error - getRequestToken failed Exception: <br>
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler.getRequestTokenFromServer(OAuth1Handler.java:169)
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler._performOAuth1Dance(OAuth1Handler.java:656)
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler.performOAuth1Dance(OAuth1Handler.java:649)
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler._acquireToken(OAuth1Handler.java:625)
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler.acquireToken(OAuth1Handler.java:580)
at com.ibm.sbt.services.endpoints.OAuthEndpoint.authenticate(OAuthEndpoint.java:234)
at com.ibm.sbt.services.client.ClientService.forceAuthentication(ClientService.java:281)
at com.ibm.sbt.services.client.ClientService.processResponse(ClientService.java:1123)
at com.ibm.sbt.services.client.ClientService._xhr(ClientService.java:1041)
at com.ibm.sbt.services.client.ClientService.execRequest(ClientService.java:1006)
at com.ibm.sbt.services.client.ClientService.xhr(ClientService.java:966)
at com.ibm.sbt.services.client.ClientService.get(ClientService.java:842)
at com.ibm.sbt.services.client.ClientService.get(ClientService.java:838)
at com.ibm.sbt.services.client.base.BaseService.retrieveData(BaseService.java:352)
at com.ibm.sbt.services.client.base.BaseService.retrieveData(BaseService.java:376)
at com.ibm.sbt.services.client.base.BaseService.retrieveData(BaseService.java:327)
at com.ibm.sbt.services.client.base.BaseService.getEntities(BaseService.java:187)
at com.ibm.sbt.services.client.connections.communities.CommunityService.getPublicCommunities(CommunityService.java:164)
at com.ibm.sbt.services.client.connections.communities.CommunityService.getPublicCommunities(CommunityService.java:146)
at servlets.SmartCloudTestServlet.doGet(SmartCloudTestServlet.java:82)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:575)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1224)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:774)
at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:456)
at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:178)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:136)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:97)
at com.ibm.sbt.util.SBTFilter.doFilter(SBTFilter.java:53)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:195)
at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:91)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:928)
at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1025)
at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3751)
at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:304)
at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:962)
at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1662)
at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:195)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:452)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:511)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:305)
at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:276)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214)
at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113)
at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138)
at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204)
at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775)
at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1690)
Caused by: java.lang.NullPointerException
at java.net.URLEncoder.encode(URLEncoder.java:197)
at com.ibm.sbt.security.authentication.oauth.consumer.OAuth1Handler.getRequestTokenFromServer(OAuth1Handler.java:156)
... 51 more
[4/4/14 12:01:56:560 CEST] 00000038 SystemOut O Problem Occurred while fetching public communities: Problem occurred while fetching public communities
Here's what I've done so far:
Create a new Servlet application.
I'm using RuntimeFactoryStandalone.
Added managed-beans.xml and sbt.properties (both from samples app) to /WEB-INF/.
I'm running the application on WebSphere Application Server. (I also tried the same code in a Portlet on WebSphere Portal)
Added the SmartCloud key, secret and appId to the properties file.
I'm using this code:
try {
CommunityService svc = new CommunityService("smartcloud");
CommunityList communities = svc.getPublicCommunities();
System.out.println("Listing public communities , Total communities found : " + communities.getTotalResults());
} catch (Throwable e) {
System.out.println("Problem Occurred while fetching public communities: " + e.getMessage());
//e.printStackTrace();
}
I'm getting the same error if I manually use a SmartCloudOAuthEndpoint.
Am I forgetting something here?
Update:
My manual endpoint:
SmartCloudOAuthEndpoint endpoint = new SmartCloudOAuthEndpoint();
endpoint.setUrl("https://apps.na.collabserv.com");
endpoint.setConsumerKey("a91..----REMOVED FOR STACKOVERFLOW----..");
endpoint.setConsumerSecret("905..----REMOVED FOR STACKOVERFLOW----..");
endpoint.setRequestTokenURL("https://apps.na.collabserv.com/manage/oauth/getRequestToken");
endpoint.setAuthorizationURL("https://apps.na.collabserv.com/manage/oauth/authorizeToken");
endpoint.setAccessTokenURL("https://apps.na.collabserv.com/manage/oauth/getAccessToken");
endpoint.setAppId("RonnieTest");
endpoint.setApiVersion("apiVersion");
//endpoint.setHttpProxy("localhost:8888");
endpoint.setForceTrustSSLCertificate(true);
endpoint.setSignatureMethod("PLAINTEXT");
endpoint.setCredentialStore("SmartCloudStore");
endpoint.setAuthenticationService("communities/service/atom/communities/my");
I'm using this Internal App in SmartCloud:

I solved it. I wasn't passing ServletRequest and ServletResponse to my Context. Turns out that getCallbackUrl(Context context) in OAuthHandler is the first method that actually needs the request to build the callback URL.

Related

Trying to use Azure Pod Identity fails a number of times, before finally succeeding

Intro: I'm trying to get Azure Pod Identity to work in our cluster to read secrets from a KeyVault, and am mostly succeeding (so far so good). For the time being, we have two keyvaults, two AzureIdentity's, two AzureIdentityBinding's and two Pods using each their keyvault.
While testing, both pods are equal - only difference being their aadpodidbinding and an environment variable indicating what keyvault to use. At startup, the pod connects to the KeyVault, reads two values and prints them with Console.WriteLine. If the connection fails, the pod will crash and k8s will restart it.
The problem: One pod might startup being able to read from the keyvault immediately, while the other will crash and restart for - what seems to be - rather consistently 5 times before being able to get an access token.
When it fails, the following Exception is thrown:
Unhandled Exception: Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/******************. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/******************. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. MSI ResponseCode: Forbidden, Response: no AzureAssignedIdentity found for pod:default/kv-test-be
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/******************. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Environment variable LOCALAPPDATA not set.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net, Authority: https://login.windows.net/******************. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. No such file or directory
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAuthResultAsyncImpl(String authority, String resource, String scope)
at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.<get_KeyVaultTokenCallback>b__8_0(String authority, String resource, String scope)
at Microsoft.Azure.KeyVault.KeyVaultCredential.PostAuthenticate(HttpResponseMessage response)
at Microsoft.Azure.KeyVault.KeyVaultCredential.ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretsWithHttpMessagesAsync(String vaultBaseUrl, Nullable`1 maxresults, Dictionary`2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretsAsync(IKeyVaultClient operations, String vaultBaseUrl, Nullable`1 maxresults, CancellationToken cancellationToken)
at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.LoadAsync()
at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at KeyvaultTest.Program.Main(String[] args) in /app/src/Program.cs:line 16
The behaviour is similar when using FlexVolume (which eventually one group of our pods will use in production), but I find it easier to relate to the error with two equal pods.
While waiting for the pod to succeed, I'm seeing both "binding removed" and "binding applied" messages in mic's log.
My questions:
Is this behaviour "as intendend" and perhaps documented somewhere?
Is there a setting I can apply to make the "remove - apply" cycle faster?
Is there anything else that can be done to improve the time between pod creation and the identity binding being applied? Is this issue perhaps related to https://github.com/Azure/aad-pod-identity/issues/145
Sourcecode:
Program.cs
using System;
using System.IO;
using System.Threading;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace KeyvaultTest
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting Keyvault read");
var configuration = new ConfigurationBuilder()
.AddAzureKeyVault()
.Build();
var test1 = configuration.GetValue<string>("jtest");
Console.WriteLine(test1);
var test2 = configuration.GetValue<string>("jtest:jtest");
Console.WriteLine(test2);
Console.WriteLine("Finished Keyvault read");
}
}
}
KeyVaultConfiguration.cs.cs
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
namespace KeyvaultTest
{
public static class KeyVaultConfiguration
{
public static IConfigurationBuilder AddAzureKeyVault(this IConfigurationBuilder builder)
{
var builtConfig = builder.Build();
var keyVaultName = Environment.GetEnvironmentVariable("KV_NAME");
if (string.IsNullOrWhiteSpace(keyVaultName))
{
throw new Exception("KV_NAME is not defined");
}
Console.WriteLine($"Using KV_NAME = {keyVaultName}");
var azureServiceTokenProvider = new AzureServiceTokenProvider();
var keyVaultClient = new KeyVaultClient(
new KeyVaultClient.AuthenticationCallback(
azureServiceTokenProvider.KeyVaultTokenCallback));
builder.AddAzureKeyVault(
$"https://{keyVaultName}.vault.azure.net/",
keyVaultClient,
new DefaultKeyVaultSecretManager());
return builder;
}
}
}
Any help, hints or ideas are much appreciated.
Note: I've posted this same question to the Issue board on of the project's github page https://github.com/Azure/aad-pod-identity/issues/181
We were facing the same issue. We overcame this issue by upgrading AAD Pod Identity. Our version was 1.5 and upgrading this one to 1.7 resolved our issue.
Before that, we had also upgraded the packages (Microsoft.Azure.Services.AppAuthentication & Azure.Security.KeyVault.Secrets) that our applications were using to the latest versions but it wasn't enough.

Client Id is not setting while using OAuth2RestTemplate to invoke rest api in spring

I am trying to invoke the Oauth2 secured rest API from my client appliaction using Oauth2RestTemplate
The client Id is not setting while trying to get the access token
Please help me to get the sample code or link to working code
AppConfig.java
#Bean
#Primary
public OAuth2ProtectedResourceDetails getOAuth2ProtectedResourceDetails()
{
ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
details.setAccessTokenUri("External Url , Ex: https://XXX/oauth2/v0/token");
details.setClientId("*******");
details.setClientSecret("******");
details.setGrantType("client_credentials");
return details;
}
#Bean
#Primary
public OAuth2RestTemplate createOAuth2RestTemplate() {
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(getOAuth2ProtectedResourceDetails(), new DefaultOAuth2ClientContext(accessToken));
return restTemplate;
}
In ClientInvoker.java
String URL= "Get the Accounts Url";
oAuth2RestTemplate.getForEntity("URL", Object.class)
Exception
Caused by: org.springframework.beans.BeanInstantiationException:
Failed to instantiate
[org.springframework.security.oauth2.client.OAuth2RestTemplate]:
Factory method 'createOAuth2RestTemplate' threw exception; nested
exception is error="access_denied", error_description="Access token
denied." at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at
org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 25 more Caused by: error="access_denied",
error_description="Access token denied." at
org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport.retrieveToken(OAuth2AccessTokenSupport.java:142)
You seem to have issues with your resource server. Confirm the following
Its pointing to the same authorization server/instance as your client.
Confirm that the expiry window on the clients token is no less than 1ms(lol).. yes yes.. please check.
Regards

How to avoid Spring Data Rest throwing HTTP 400 when an AccessDeniedException occurs on a controller

I have a spring data rest application with a simple one-to-many relationship.
(1 organization contains zero or more employees).
In a scenario without any security, I can add employees to the organization like this :
curl -v -H "Content-Type:application/json" -d '{"name":"name1","organization":"http://localhost:8080/api/organizations/1"}' http://localhost:8080/api/employee
When the employee payload is pushed to the rest controller, Spring Data Rest will convert the organization uri to an organization entity, hook it up to the employee, and everything works fine.
However, suppose I start securing my organization API and I only want to allow authorized users to see an organization (based on some business logic).
#RepositoryRestResource
public interface OrganizationController extends CrudRepository<Organization, Long> {
#PreAuthorize("#securityService.isAllowedToSeeTheOrganization(#id)")
Organization findOne(#P("id") Long id);
}
The SecurityService implements some business logic to determine if the user is able to retrieve an organization based on his profile :
#Service
public class SecurityService {
public boolean isAllowedToSeeOrganization(Long organizationId) {
return isAdmin() || belongsToOrganization(organizationId);
}
private boolean isAdmin() {
return SecurityContextHolder.getContext().getAuthentication().getAuthorities().contains(new SimpleGrantedAuthority(ADMIN.getRoleName()));
}
private boolean belongsToOrganization(Long organizationId) {
return organizationId == Long.parseLong(getUserDetails().get(ORGANIZATION_ID_FIELD).toString());
}
protected Map<String,Object> getUserDetails() {
JwtAuthentication jwtAuthentication = (JwtAuthentication) SecurityContextHolder.getContext().getAuthentication();
return jwtAuthentication.getJwtClaimsSet().getClaims();
}
}
This off course will also have an effect on the call above, as it will no longer be able to convert the organization uri into an entity.
However, instead of throwing a 403 Forbidden, the API call fails with an HTTP 400 (Bad Request) and the following body:
{
"cause":{
"cause":{
"cause":null,
"message":"Access is denied"
},
"message":"Access is denied (through reference chain: com.example.Employee[\"organization\"])"
},
"message":"Could not read document: Access is denied (through reference chain: com.example.Employee[\"organization\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Access is denied (through reference chain: com.example.Employee[\"organization\"])"
}
In the logs :
Caused by: com.fasterxml.jackson.databind.JsonMappingException: Access is denied (through reference chain: com.example.Employee["organization"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1599) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:359) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3798) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2922) ~[jackson-databind-2.8.5.jar:2.8.5]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:237) ~[spring-web-4.3.5.RELEASE.jar:4.3.5.RELEASE]
... 97 common frames omitted
Caused by: org.springframework.security.access.AccessDeniedException: Access is denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65) ~[spring-security-core-4.1.4.RELEASE.jar:4.1.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at com.sun.proxy.$Proxy156.findOne(Unknown Source) ~[na:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40]
at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40]
at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:216) ~[spring-core-4.3.5.RELEASE.jar:4.3.5.RELEASE]
at org.springframework.data.repository.support.ReflectionRepositoryInvoker.invoke(ReflectionRepositoryInvoker.java:265) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.repository.support.ReflectionRepositoryInvoker.invokeFindOne(ReflectionRepositoryInvoker.java:140) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.repository.support.CrudRepositoryInvoker.invokeFindOne(CrudRepositoryInvoker.java:91) ~[spring-data-commons-1.12.6.RELEASE.jar:na]
at org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory$UnwrappingRepositoryInvoker.invokeFindOne(UnwrappingRepositoryInvokerFactory.java:130) ~[spring-data-rest-core-2.5.6.RELEASE.jar:na]
at org.springframework.data.rest.core.UriToEntityConverter.convert(UriToEntityConverter.java:123) ~[spring-data-rest-core-2.5.6.RELEASE.jar:na]
at org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module$UriStringDeserializer.deserialize(PersistentEntityJackson2Module.java:516) ~[spring-data-rest-webmvc-2.5.6.RELEASE.jar:na]
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:101) ~[jackson-databind-2.8.5.jar:2.8.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:357) ~[jackson-databind-2.8.5.jar:2.8.5]
The fact that it leaks internal information back to the client makes me think there is something wrong.
I would simply like the api to return a 403 Forbidden in this case, or have some way of customising this error message.
How would I go about doing that?
Naturally you should use the standard Spring exception handling mechanisms but your problem is a bit more complicated than usually. I've tried my solution on a demo project and this should work.
In your case the AccessDeniedException is wrapped in a JsonMappingException, which itself is wrapped in a HttpMessageNotReadableException. This is what Spring exception handling gets:
HttpMessageNotReadableException
|---JsonMappingException
|---AccessDeniedException
According to this ticket in the Spring issue tracker #ExceptionHandler methods can match wrapped Exceptions since Spring 4.3, but only up to one level deep. Using an #ExceptionHandler for AccessDeniedException won't work because it's nested two levels below the exception Spring has received.
You could alter how deep in the exception chain Spring is looking for matching handlers, but if it's only for this problem i'd just define an exception handler that does that:
#ControllerAdvice
public class ExceptionAdvice {
#ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<String> accessDenied(Exception e) throws Exception {
Throwable cause = e.getCause();
if (cause != null) {
Throwable nestedCause = cause.getCause();
if (AccessDeniedException.class.isAssignableFrom(nestedCause.getClass())) {
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
}
}
throw e;
}
}
You could customise the matching (maybe search the complete exception chain for the wanted exception?) and add a return message.
Note that the handler is defined in its own class - since your EmployeeController presumably is an interface, like your OrganizationController, the #ExceptionHandler method can't be defined inside it (default method doesn't work either).

PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed

From Pro Spring Security book by Carlo Scarioni, I'm trying to integrate Spring Application with CAS Server. I followed every step that the book instructed, still I'm stuck with this error. Please help me out.
SEVERE: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1904)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:279)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:273)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1446)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:901)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:837)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1023)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1301)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:311)
at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:291)
at org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:32)
at org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:187)
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:140)
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:126)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.cas.web.CasAuthenticationFilter.attemptAuthentication(CasAuthenticationFilter.java:242)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:483)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:412)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:351)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:47)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:634)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:66)
at org.eclipse.jetty.server.bio.SocketConnector$ConnectorEndPoint.run(SocketConnector.java:254)
at org.eclipse.jetty.server.ssl.SslSocketConnector$SslConnectorEndPoint.run(SslSocketConnector.java:665)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
at java.lang.Thread.run(Thread.java:745)
Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:350)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:260)
at sun.security.validator.Validator.validate(Validator.java:260)
at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1428)
... 55 more
Caused by: java.security.cert.CertPathValidatorException: signature check failed
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:159)
at sun.security.provider.certpath.PKIXCertPathValidator.doValidate(PKIXCertPathValidator.java:347)
at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(PKIXCertPathValidator.java:191)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:279)
at sun.security.validator.PKIXValidator.doValidate(PKIXValidator.java:345)
... 61 more
Caused by: java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:451)
at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:160)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:139)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:133)
... 65 more
2015-08-29 02:46:50.472:WARN:oejs.ServletHandler:/j_spring_cas_security_check
java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: signature check failed
at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:328)
at org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:291)
at org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:32)
at org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:187)
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:140)
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:126)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:156)
at org.springframework.security.cas.web.CasAuthenticationFilter.attemptAuthentication(CasAuthenticationFilter.java:242)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:195)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:483)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:412)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:351)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.BlockingHttpConnection.handleRequest(BlockingHttpConnection.java:47)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:634)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
at org.eclipse.jetty.server.BlockingHttpConnection.handle(BlockingHttpConnection.java:66)
at org.eclipse.jetty.server.bio.SocketConnector$ConnectorEndPoint.run(SocketConnector.java:254)
at org.eclipse.jetty.server.ssl.SslSocketConnector$SslConnectorEndPoint.run(SslSocketConnector.java:665)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:599)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:534)
at java.lang.Thread.run(Thread.java:745)
The SSL handshake exception will occur if cas server to cas client (jar files will behave as client) communication is not happened, First check the network things like communication between both servers, firewall and port blocking, if every thing is good then this problem is because of SSL certificate, make sure to use the same certificate in both CAS server and client(Spring security app) applications.
As i can't comment yet, i'll just extend to #Kamal's answer. I was learning through the same book, but i was using Tomcat as a difference, so i can't really give you the same answer as i've never used Jetty:
As he said, your SSL is not working as it should. The certificate is not being accepted by your browser and/or server, so it can't authenticate, and thus, SSL handshake gets rejected. You need to be sure that you've added the certificate CAS.crt to your JVM cacerts, as he explains on the book(198-199), and check if it's correctly there . And then you need to add the jetty-ssl.keystore to Jetty, with the password that you used, so that it can used to make the right connection. Also, you need to be positively sure that it's written localhost as the cn name, as it won't work otherwise. This would change depending on your enviroment(production, testing, just learning...), but this is the necessary for making it work as the book described.
Hope that i'm not too off here, but i hope it helped.
I have faced this issue and found that SSL certificate was expired.
After replacing expired SSL certificate by latest certificate the issue was resolved.
I am using Spring 2.2.5 now with Java 11
Try to add into the Spring Application context the RestTemplate bean, in order to accept all the certificates, just like this:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
HttpComponentsClientHttpRequestFactory customRequestFactory = new HttpComponentsClientHttpRequestFactory();
customRequestFactory.setHttpClient(httpClient);
return builder.requestFactory(() -> customRequestFactory).build();
}
Then, in your client class with the server communication, you have to add the bean RestTemplate restTemplate and pass it in the constructor.
Then, in a method, you have to write the remote rest end point invocation like this:
private YourSpecificResponseJSONClass getYourRemoteResponse() {
YourSpecificResponseJSONClass ret = getYourDefaultJSONResponseInCaseOfAnyException();
try {
ret = restTemplate.getForObject("<yourRemoteURL>", YourSpecificResponseJSONClass.class);
} catch (Throwable t) {
//log whatever
}
return ret;
}
Check your system date. It worked for me when I corrected it. This usually comes in SLES distros.
Below solution is working fine for me.
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
HttpClient httpClient = HttpClient.create().secure(t ->
t.sslContext(sslContext) );
WebClient webClient = WebClient.builder()
.baseUrl("any-url")
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
Normally is accompained by this error as first entry "NotAfter: Sun Sep 25 02:51:03 PDT 2022" indicating cert not valid anymore

Error when trying to load the interceptors dynamically in Spring Security

I have configured spring security for generate interceptors dynamcally from DB. I have guide here. When I try to access a home page from login page get the following error:
An Authentication object was not found in the SecurityContext
This error happen in the class AbstractSecurityInterceptor in the following lines (I did debugging):
if (SecurityContextHolder.getContext().getAuthentication() == null) {
credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound",
"An Authentication object was not found in the SecurityContext"), object, attributes);
}
This is log:
org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:339)
org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:198)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
This is link of my file configuration of Spring Security
I don't understand because happen this error, user with to login on in my app have SYS_ADMIN role. This role is authorized to access to homepage...
I've debugged and checked that class InterceptorApplicationService (This class implements interface FilterInvocationSecurityMetadataSource) return SYS_ADMN role and list of roles in the methods getAttributes and getAllConfigAttributes respectively
I solved the problem. Here is post

Resources