In Axis2/Rampart, how can I get SAML Assertion in PasswordCallBackHandler - axis2

I am securing my SOAP based Web Services using STS. The tokens are SAML 1.0 tokens. The SAML tokens are added in SOAP Header as security header. I need the SAMLAssertions as I need to get the nameIdentifier from the SAMLAssertion.
Can I get hold of the SAMLAssertion in PasswordCallBackHandler class. Is there any other way of doing it.

Finally I was able to identity a way to do what I wanted. I will list down the solution point wise :
Its not possible via Password CallBackHandler as axis does not give access to the MessageContext.
Solution is to create a Custom Handler class which extends org.apache.axis2.handlers.AbstractHandler . Since in my case its a SAML2 Security Token, I wanted my handler to be called 'post-security' phase in 'InFlow' phaseorder. This ensures that the security header has passed the security phase. The handler class has a invoke method which has a MessageContext as its parameter. MessageContext gives you access to the whole SOAPEnvelope and its content. Following is the skeleton code you can build on :
public class LIMSConHandler extends AbstractHandler {
private Log LOG = LogFactory.getLog(LIMSConHandler.class);
public InvocationResponse invoke(MessageContext ctx) throws AxisFault {
//following code gives you access to the soapEnvelope
SOAPEnvelope msgEnvelope = ctx.getEnvelope();
SOAPHeader msgHeader = msgEnvelope.getHeader();
//add your logic to extract the security header and SAML assertion
return InvocationResponse.CONTINUE;
}
Bind this handler to the 'Post-Security' custom phase in axis2.xml
<phaseOrder type="InFlow">
.........
<phase name="Security"/>
<phase name="PostSecurity">
<handler name="LIMSConHandler" class="labware.web.ws.control.LIMSConHandler"/>
I welcome input on this.

Related

Register dependent services on every request

I am working in Multi-tenant solution primarily there are 2 type of applications
WebAPI
Console app to process message from queue
I have implemented dependency injection to inject all services. I have crated TenantContext class where I am resolving tenant information from HTTP header and it's working fine for API, but console application getting tenant information with every message (tenant info is part of queue message) so I am calling dependency injection register method on every incoming message which is not correct, do you have any suggestion/solution here?
The way I am resolving ITenantContext in API
services.AddScoped<ITenantContext>(serviceProvider =>
{
//Get Tenant from JWT token
if (string.IsNullOrWhiteSpace(tenantId))
{
//1. Get HttpAccessor and processor settings
var httpContextAccessor =
serviceProvider.GetRequiredService<IHttpContextAccessor>();
//2. Get tenant information (temporary code, we will get token from JWT)
tenantId = httpContextAccessor?.HttpContext?.Request.Headers["tenant"]
.FirstOrDefault();
if (string.IsNullOrWhiteSpace(tenantId))
//throw bad request for api
throw new Exception($"Request header tenant is missing");
}
var tenantSettings =
serviceProvider.GetRequiredService<IOptionsMonitor<TenantSettings>>();
return new TenantContext(tenantId, tenantSettings );
});
Create two different ITenantContext implementations. One for your Web API, and one for your Console application.
Your Web API implementation than might look as follows:
public class WebApiTenantContext : ITenantContext
{
private readonly IHttpContextAccessor accessor;
private readonly IOptionsMonitor<TenantSettings> settings;
public WebApiTenantContext(
IHttpContextAccessor accessor,
IOptionsMonitor<TenantSettings> settings)
{
// Notice how the dependencies are not used in this ctor; this is a best
// practice. For more information about this, see Mark's blog:
// https://blog.ploeh.dk/2011/03/03/InjectionConstructorsshouldbesimple/
this.accessor = accessor;
this.settings = settings;
}
// This property searches for the header each time its called. If needed,
// it can be optimized by using some caching, e.g. using Lazy<string>.
public string TenantId =>
this.accessor.HttpContext?.Request.Headers["tenant"].FirstOrDefault()
?? throw new Exception($"Request header tenant is missing");
}
Notice that this implementation might be a bit naive for your purposes, but hopefully you'll get the idea.
This class can be registered in the Composition Root of the Web API project as follows:
services.AddScoped<ITenantContext, WebApiTenantContext>();
Because the WebApiTenantContext has all its dependencies defined in the constructor, you can do a simple mapping between the ITenantContext abstraction and the WebApiTenantContext implementation.
For the Console application, however, you need a very different approach. The WebApiTenantContext, as shown above, is currently stateless. It is able to pull in the required data (i.e. TenantId) from its dependencies. This probably won't work for your Console application. In that case, you will likely need to manually wrap the execution of each message from the queue in a IServiceScope and initialize the ConsoleTenantContext at the beginning of that request. In that case, the ConsoleTenantContext would look merely as follows:
public class ConsoleTenantContext : ITentantContext
{
public string TenantId { get; set; }
}
Somewhere in the Console application's Composition Root, you will have to pull messages from the queue (logic that you likely already have), and that's the point where you do something as follows:
var envelope = PullInFromQueue();
using (var scope = this.serviceProvider.CreateScope())
{
// Initialize the tenant context
var context = scope.ServiceProvider.GetRequiredService<ConsoleTenantContext>();
content.TenantId = envelope.TenantId;
// Forward the call to the message handler
var handler = scope.ServiceProvider.GetRequiredService<IMessageHandler>();
handler.Handle(envelope.Message);
}
The Console application's Composition Root will how have the following registrations:
services.AddScoped<ConsoleTenantContext>();
services.AddScoped<ITenentContext>(
c => c.GetRequiredServices<ConsoleTenantContext>());
With the registrations above, you register the ConsoleTenantContext as scoped. This is needed, because the previous message infrastructure needs to pull in ConsoleTenantContext explicitly to configure it. But the rest of the application will depend instead on ITenantContext, which is why it needs to be registered as well. That registration just forwards itself to the registered ConsoleTenantContext to ensure that both registrations lead to the same instance within a single scope. This wouldn't work when there would be two instances.
Note that you could use the same approach for Web API as demonstrated here for the Console application, but in practice it's harder to intervene in the request lifecycle of Web API compared to doing that with your Console application, where you are in full control. That's why using an ITenantContext implementation that is itself responsible of retrieving the right values is in this case an easier solution for a Web API, compared to the ITenantContext that is initialized from the outside.
What you saw here was a demonstration of different composition models that you can use while configuring your application. I wrote extensively about this in my series on DI Composition Models on my blog.

How to implement customized authentication in Spring Boot Application

I am building a web app with Spring Boot. Post requests can be made by a phone app to upload data in form of xml to the cloud. The phones that are allowed to push data are required to be registered company phones. The way to authenticate the APIs calls is to look up the android ID of the phone in a corporate database. It will accept the data only if the Android ID exists. The idea is to embed the android ID in the header of requests. Since it is not a typical way for authentication, how do I implement it with Spring Security? Or we don't even need Spring Security. Just extract the Android ID from the header and look it up in database. Reject the request if it is not a valid ID. Any advice would help.
Nothing prevents you from using Authorization header in a creative way, i.e., by embedding the Android ID into it. Then, in order to add authentication to your endpoints, you can use an AOP interceptor:
Protected operation marker interface:
#Target({ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface ProtectedOperation {
}
Interceptor:
#Aspect
#Component
public class SecurityAspect {
private CorporateService corpService; // this is your custom service to check Android IDs
#Autowired
public SecurityAspect(CorporateService corpService) {
this.corpService = corpService;
}
#Around("#annotation(operation)")
public Object protectedOperationPermissionCheck(final ProceedingJoinPoint pjp, final ProtectedOperation operation) throws Throwable {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
String header = requestAttributes.getRequest().getHeader("Authorization");
String androidId = // get the ID from header - try not to use existing authorization header formats like Bearer, Negotiate etc. to avoid collision with other authentication systems
if (corpService.isAuthorized(androidId)) {
return pjp.proceed();
}
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.flushBuffer();
return null;
}
}
Make sure to add the spring-boot-starter-aop dependency to your pom.xml, for #Aspect support
EDIT: to protect an endpoint, annotate the endpoint method in your controller with #ProtectedOperation, and add #EnableAspectJAutoProxy to your Spring Boot application

Dropwizard Authentication with POST calls failing

I was trying out Dropwizard authentication in my code but facing some issue in POST call at runtime, although its working fine with GET. this is how I am using this in the GET call:
#Override
#GET
#Path("/auth")
public Response doAuth(#Auth User user) {
//do something
}
And then in Post call which is not working:
#Override
#POST
#Path("/")
public Response createLegalEntity(#Auth User user, LegalEntity createLegalEntity) {
// do something
}
While running it is throwing following error:
SEVERE: Missing dependency for method public javax.ws.rs.core.Response org.flipkart.api.LegalEntityResource.createLegalEntity(com.yammer.dropwizard.authenticator.User,org.flipkart.model.LegalEntity) at parameter at index 0
I am new to Dropwizard and not able to figure out the cause of the problem.
UPDATE
Here is how I have registered my ldap authentication configs:
final LdapConfiguration ldapConfiguration = configuration.getLdapConfiguration();
Authenticator<BasicCredentials, User> ldapAuthenticator = new CachingAuthenticator<>(
environment.metrics(),
new ResourceAuthenticator(new LdapAuthenticator(ldapConfiguration)),
ldapConfiguration.getCachePolicy());
environment.jersey().register(new AuthDynamicFeature(
new BasicCredentialAuthFilter.Builder<User>()
.setAuthenticator(ldapAuthenticator)
.setRealm("LDAP")
.buildAuthFilter()));
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
The most likely reason is that you have not configured that auth feature correctly. The one thing that most people forget about is the AuthValueFactoryProvider.Binder. An instance of this class also needs to be registed. This would definitely cause the error you are seeing, if unregistered.
// If you want to use #Auth to inject a custom Principal type into your resource
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
From Basic Authentication docs
See also:
My comment for Dropwizard issue regarding the same problem. You will get a good explanation of the what causes the problem.

How to get mule security context or security principal reference in mule flow

Was trying out authentication and authorisation in mule and got it working. Now I want the reference to the mule security context specifically the principal object reference to be used within the flow . How to get hold of the reference to principal object in mule inside a flow?
link to mule xml
Security context is available through MuleSession and this session is available through eventContext. To get eventContext reference, following can be done.
This can be achieved by implementing Callable. Create the following java class. Now place a java component in the mule flow where this has to be invoked and configure with the created java class. Mule calls automatically onCall method which has eventContext as a parameter and no extra configuration is required to invoke.
The example java component gets the security content from session and from that it gets the security principal and stores it in a flow variable "user" which can be used by other flow elements which appear after this java component in the flow.
import org.mule.api.MuleEventContext;
import org.mule.api.lifecycle.Callable;
import org.mule.api.security.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
public class GetSecurityPrincipalCallable implements Callable {
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
Authentication auth = eventContext.getSession().getSecurityContext()
.getAuthentication();
UserDetails principal = (UserDetails) auth.getPrincipal();
System.out.println("username is : " + principal.getUsername());
eventContext.getMessage().setInvocationProperty("user", principal);
return null;
}
}

Invoke a Controller Action from an Interceptor on Asp.Net MVC (Castle Windsor)

Is there any way this. I want to invoke an action with parameter (or parameterless at least) like below.
My situation is;
Interceptor not contains any reference from MVC, Interceptor is located at ApplicationService layer.
This is a service Interceptor.
public class ControllerInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var retVal = (ResponseDTOBase) invocation.ReturnValue;
if (retVal.ResponseCode == UsrNotAuth)
{
//Invoke Controller Action With passsing parameter (retVal)
}
invocation.Proceed();
}
}
Any ideas ? Thanks.
May I offer you another approach for request authorization. MVC is a state machine in its core principle. State machines have actions, triggers and guards. There is already such a 'guard' in MVC for the very purpose of intercepting controller actions and checking for the user privileges. This is the AuthorizeAttribute. This class implements IAuthorizationFilter. Another aspect is that authorization and authentication should happen before they reach your services. What I mean exactly is that there are two types of authorization :
Action Authorization and
Data Authorization.
The first type of authorization you can implement with AuthorizeAttribute or your custom attribute implementation of IAuthorizationFilter + FilterAttribute. Here is an example implementation of such an attribute for a SPA (Single Page Application) that works with ajax requests :
The attribute :
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class LoggedOrAuthorizedAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
CheckIfUserIsAuthenticated(filterContext);
}
private void CheckIfUserIsAuthenticated(AuthorizationContext filterContext)
{
// If Result is null, we’re OK: the user is authenticated and authorized.
if (filterContext.Result == null)
return;
// If here, you’re getting an HTTP 401 status code. In particular,
// filterContext.Result is of HttpUnauthorizedResult type. Check Ajax here.
// User is logged in but this operation is not allowed
if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.HttpContext.Request.IsAjaxRequest())
{
//filterContext.HttpContext.Response.StatusCode = 401;
JsonNetResult jsonNetResult = new JsonNetResult();
jsonNetResult.Data = JsonUtils.CreateJsonResponse(ResponseMessageType.info, "msgOperationForbiddenYouAreNotInRole");
filterContext.Result = jsonNetResult;
//filterContext.HttpContext.Response.End();
}
}
}
If you use pure MVC there is an example implementation here.
The usage :
In your controller
[LoggedOrAuthorized(Roles = Model.Security.Roles.MyEntity.Create)]
public ActionResult CreateMyEntity(MyEntityDto myEntityDto)
{
...
}
You can apply this on every controller action and block the user even before the controller is reached.
You can supply Loggers and other 'plumbing' through Castle Windsor inside your filters in order to record the events.
A very good and important links and comments are available in this answer of a similar question. These links provide very good guide for proper implementation too.
The other type of authorization - Data Access Authorization can be handled in the service or in the controller. I personally prefer to handle all kinds of authorization as soon as possible in the pipeline.
General practice is not to show to the user any data or action that he is not authorize to view or to execute commands upon it. Of course you have to double check this because the user can modify the POST and GET requests.
You can make simple interface with implementation IDataAccessService and control data access by passing user id and entity id to it.
Important thing is that you should not throw exception when the user is not authorized because this is no exception at all. Exception means that your program is in an unexpected state which prohibits its normal execution. When a user is not authorized this is not something unexpected - it is very well expected. That is why in the example implementation a message is returned rather then exception.
Another subtlety is that "exceptions" are handled differently by the .NET framework and they cost a lot more resources. This means that your site will be very vulnerable to easy DDOS outages or even they can perform not as they can. General rule is that if you control your expected program flow through exceptions you are not doing it properly - redesign is the cure.
I hope this guides you to the right implementation in your scenario.
Please provide the type of the authorization you want to achieve and parameters you have at hand so I can suggest a more specific implementation.