I am creating a WCF service which uses basicHttpBinding(SOAP). I would like each request to the webservice to require an account name and a key, essentially a username and password. Currently these values are being passed as arguments to each exposed method. Is this the proper way to handle this situation? It seems to violate DRY, and I'm guessing that there is an easier, built in way. I have seen some examples of inserting a username and a password into the headers by intercepting the request but that approach seems to add quite a bit of effort for clients connecting.
Thanks!
Rather then sending the user name and password ever request, why not have a login method that returns a token, and pass that?
If you want to minimize DRY you can do the following:
First, make a generic class similar to the following that all request contracts inherit from (besides Login and Logout):
[MessageContract]
public abstract class AuthenticatedRequest <T> {
[MessageHeader]
public string Token { get; set;]
}
Now make a private function called private bool IsAuthenticated(string Token) that checks the token. This minimizes the ceremony of checking for authentication.
Related
I need to access the user's password in a Jetty application after authentication, and can't figure out how.
I am migrating a set of web pages away from basic authentication in an embedded Jetty servlet application. I cannot, however, completely remove basic authentication from all of the services that these pages call, so I need to forward the user credentials in some cases, which means storing and later retrieving the user's password.
I introduced forms authentication to the root context via the standard markup in web.xml, which works fine but I can find no way of getting the user credentials programatically. As far as I can tell there is no way to place a Filter on j_security_check to intercept and store the form parameters in the session state. Jetty provides all the user credentials in the session state but this is in a container-specific key and although the application is currently tied to Jetty I would strongly prefer a container-agnostic solution. Here are some specific questions that I've tried to formulate after going down a number of seemingly dead-end streets:
How can I obtain the user's password after login? Even if I moved the services away from basic authentication I would still need to perform some secondary action such as obtaining a token, in which case I would still need their credentials under my control for a brief period.
Assuming I can't obtain the user's password directly, perhaps I can leverage something in the container to store the credentials. I can implement my own LoginService that wraps the actual implementation, but that class does not have access to the HttpSession or Request objects. Where is the proper place to do this?
If I need to implement a custom login solution, I'm not quite sure where to start...the FormAuthenticator has a lot of complicated session state management that I would like to preserve and not reproduce willy-nilly, and I would still prefer to defer to the container standard as much as possible. Is there some standard method for extending or overriding the j_security_check logic?
I finally found one solution, for anyone else attempting similar - and I've found quite a few other posts from confused devs, and some badly hacked together workarounds. I believe this one is correct, although you must do the URL filtering yourself and it leaves open the question as to why this is possible, if indeed j_security_check should be exempt from this type of interception for security reasons, as is claimed many places online. Perhaps I am merely exploiting an unknown gap in the Jetty security measures, so I will leave this question open for a while to see if there is a more robust or explicit solution.
ServletRequestListener allows you to latch onto the j_security_check post request before it is fully initialized. There you can get both the form parameters and the session object. So in the end it was just a matter of exhausting every possible servlet-related class in Jetty until I found one that would give me access to the j_security_check request. Some code:
public class PreAuthenticationRequestListener implements ServletRequestListener {
public static final String USERNAME_KEY = "USERNAME";
public static final String PASSWORD_KEY = "PASSWORD";
#Override
public void requestDestroyed(ServletRequestEvent sre) {
}
#Override
public void requestInitialized(ServletRequestEvent sre) {
HttpServletRequest request = (HttpServletRequest)sre.getServletRequest();
if (request.getRequestURI().contains("j_security_check")) {
final String username = request.getParameter("j_username");
final String password = request.getParameter("j_password");
HttpSession session = request.getSession();
session.setAttribute(USERNAME_KEY, username);
session.setAttribute(PASSWORD_KEY, password);
}
}
}
WCF function
public void SetSession(string name)
{
HttpContext.Current.Session["abc"]=name;
}
public string GetSession(string name)
{
return HttpContext.Current.Session["abc"].ToString();
}
Proxy
using (ServiceReference1.BlackjackClient proxy = new ServiceReference1.BlackjackClient())
{
proxy.SetSession("Hello");
}
my problem is when multiple clients are accessing the service then last set session is accessed by the each client. Session are not browser request based and not recognizing the client. Which client has sent which request. What should i do to make them specific to each client. means each client must have his own session.
Please help
The service can not know which client is calling the service. Regular asp.net use of Session uses a cookie, that identifies each request and makes some internal voodoo to map the request to the correct session.
In your case, you would have to either use login from the clients to ensure that the service could identify requests, but this would not in it self solve the problem.
Since you have access to the service implementation the simplest solution would probably be to store a session identifier (a Guid) in the client, and then send this along each request to the web service thus altering
public void SetSession(string name)
{
HttpContext.Current.Session["abc"]=name;
}
public string GetSession(string name)
{
return HttpContext.Current.Session["abc"].ToString();
}
to something like
public void SetSession(string name, Guid sessionId)
{
HttpContext.Current.Session[sessionId + "_abc"]=name;
}
public string GetSession(string name, Guid sessionId)
{
return HttpContext.Current.Session[sessionId + "_abc"].ToString();
}
Modifying the method signature like this is rather ugly though, but the idea would be, that the client aids the server in identifying the caller and thus the session.
It would be cleaner to use the transport protocol to identify the caller, so if you are creating a HTTP service, you could use some http header (perhaps authorization) to contain the session identifier. If you are using SOAP the message header could contain identical information.
The session identifier could also be created at the service by a new method named something like Guid CreateSession(). But a Guid could as well be created in the client.
But again: You will need to store some unique session id or user credentials in the client and communicate them to the server in each request.
It seems like I'm barking up the wrong tree when asking this question, this question and this question.
I need to authenticate users against a custom API (in COM), and I need to keep that custom API (the COM object) alive (for that user) for future WCF calls. During authentication against that custom API, I can get back a list of custom-defined roles. I'd also like to use these for authorization of the service methods.
Moreover, I need to be able to revoke the user's session remotely. This is triggered by an event raised by the COM API.
I've got a custom UserNamePasswordValidator, but it appears that this has no mechanism for correctly setting a custom principal, so it looks like I'm heading in the wrong direction.
How do I do these three things?
You can handle authentication completely in your service. Create service contract similar to:
[ServiceContract(SessionMode=SessionMode.Required)]
public interface IService
{
// All your operations marked with [OperationContract(IsInitiating=false, IsTerminating=false)]
// Two additional operations
[OperationContract(IsInitiating=true, IsTerminating=false)]
void Login(string user, string password);
[OperationContract(IsInitiating=false, IsTerminating=true)]
void Logout();
}
Service implementing this contract has to have PerSession instancing. Implement authentication in Login method and store COM object in local field. When new client want to use such service he has to first call the Login method. So all your instances will be properly authenticated and they will store their instance of COM object.
You can also register InstanceContext and COM object to some global class which will deal with forcibly killing service instance. This will probably require some research to make it work.
Make sure that you use some secure binding (encryption) because you will send user name and password as a plain text.
I am looking for some best practices on how to handle the following scenario - flowing permissions from WCF service layer through to UI:
I have WCF services with methods that have been decorated with the PrincipalPermission attribute. I would like a means to allow a client to check if they have the required permissions before invoking the method.
A basic example of this could be checking whether a user can perform a specific function (say submitting an order), which can then be used to enable/disable a button within the UI.
Possible options are to add "chatty" operations like bool CanSubmitOrder() to the service, or instead have a single method OrderServicePermissions GetPermissions() which returns a message with a property CanSubmitOrder? I can then set the enabled state of a "Submit Order" button to the result.
So does anybody know of a better approach, or even a best practice?
Thanks in advance!
The whole point of having PrincipalPermission attributes on your service calls is that you don't have to check ahead of time whether or not the caller has the rights to call - if he doesn't, the WCF runtime will throw an exception.
Why not just rely on this built-in mechanism? Why not just put your service calls in a try..catch block and handle the exceptions if they do actually occur? It should be the "exceptional" case anyway, right?
I don't see any other "magic" way besides what you described. But the generally accepted practice would be to call and handle any exceptions if they occur.
Marc
Well, if you are able to evolve your applications to use Windows Identity Foundation (WIF) to secure your services you could achieve this using the DisplayToken property of the RequestSecurityTokenResponse.
http://msdn.microsoft.com/en-us/library/microsoft.identitymodel.protocols.wstrust.requestsecuritytokenresponse.requesteddisplaytoken.aspx
Assuming your security token service supported it, the display token could contain a claim set that would allow you to flow your permissions into the UI, say to disable controls that are bound to services the user cannot call. The display token is an extension to WS-Trust that was implemented for CardSpace so it it not likely to be very widely supported outside of the Windows world.
Be aware though, that some people think the display token is bad news and violates the 1st law of identity:
http://www.francisshanahan.com
While other people think it is a reasonable and pragmatic solution to a common problem:
http://blogs.msdn.com/b/vbertocci/archive/2007/10/31/on-displaytoken.aspx
There are two general type to implement checking logic:
Share library. Example is "RIA Services + Silverlight".
Pluses: simple to implement.
Minuses: no interoperability (only .NET); required client update for every library changing.
Implement common method validation in service part.
Pluses: interoperability, no need for client update if checking logic changed
Minuses: may be to complex because it is only on you
If we use SOA it is better to use second choice, if only you are not using applications only in your company where .NET is everywhere.
Example
Let us consider common example. We have a windows/wpf form. And there are two fields: "surname" of type string, "age" of type int; and a button "Save". We need to implement some check on client side
1) for some users button "Save" is disabled;
2) surname cannot be empty and max length is 256;
3) age cannot be less than 0;
Invoking method to save is
void Save(string surname, int age);
Create second method in the service, which return object type of PermissonAnswerDTO with validation information;
PermissonAnswerDTO SaveValidate(string surname, int age);
and main validation method
// If arguments are wrong
[FaultContract(typeof(NotSupportedException))]
// If the user have permisson to invoke this method
[FaultContract(typeof(CustomNotEnoughPermission))]
PermissonAnswerDTO Validate(string methodName, object[] methodParams);
Validation.
Invoke Validate("SaveValidate", null) on window loading. If exception of type CustomNotEnoughPermission is throwed then we block "Save" button.
If user can save then invoke user's data Validate("SaveValidate", object[2]{"Surname", "-60"};. -60 is not valid so we get answer object of type PermissonAnswerDTO with information:
ParameterName: "age",
ExceptionMessage: "age cannot be less then null".
And we can gracefully show this information to user.
My thought on this is that some day Microsoft will implement this and call as new technology as it always does. Mostly Microsoft's technologies really are not so revolutionary as it is advertised. Examples are Windows Identity Foundation and Reactive Extensions.
Full example
[DataContract]
public class ParameterExceptionExplanaitonDTO
{
[DataMember]
public string ParameterName;
[DataMember]
public string ExceptionMessage;
}
[DataContract]
public class PermissonAnswerDTO
{
[DataMember]
public bool IsValid;
[DataMember]
public ParameterExceptionExplanaitonDTO[] ParameterExceptions;
}
public class Service1 : WcfContracts.IService1
{
// If arguments are wrong
[FaultContract(typeof(NotSupportedException))]
// If the user have permisson to invoke this method
[FaultContract(typeof(CustomNotEnoughPermission))]
public PermissonAnswerDTO Validate(string methodName, object[] methodParams)
{
//1) Using Reflection find the method with name = <methodName + Validate>
//2) Using Reflection cast each object in "object[] methodParams" to the required type
//3) Invoke method
}
private PermissonAnswerDTO GetUserNameValidate(int id)
{
//logic to check param
}
public string GetUserName(int id)
{
// if the user calls method we need validate parameter
GetUserNameValidate(id);
//some logic to retreive name
}
}
I'm trying to integrate Spring Security in my web application. It seems pretty easy to do as long as you integrate the whole process of authentication and authorization.
However, both authentication and authorization seem so coupled that it's being very time-consuming for me to understand how I could split these processes, and get authentication independently of authorization.
The authentication process is external to our system (based on single sign-on) and this cannot be modified. Nevertheless, once the user succeeds this process, it's loaded in the session, including roles.
What we are trying to achieve is to make use of this information for the authorization process of Spring Security, that's to say, to force it to get the roles from the user session instead of picking it up through the authentication-provider.
Is there any way to achieve this?
If your authentication is already done using an SSO service, then you should use one of spring security's pre-authentication filters. Then you can specify a UserDetails service (possibly custom) that will use the pre-authenticated user principle to populate the GrantedAuthority's
SpringSecurity includes several pre-authentication filters including J2eePreAuthenticatedProcessingFilter and RequestHeaderPreAuthenticatedProcessingFilter. If you can't find one that works for you, its also possible, and not that hard to write your own, provided you know where in the request your SSO implementation stuffs the data. (That depends on the implementation of course.)
Just implement the Filter interface and do something like this in the doFilter method:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// principal is set in here as a header or parameter. you need to find out
// what it's named to extract it
HttpServletRequest req = (HttpServletRequest) request;
if (SecurityContextHolder.getContext().getAuthentication() == null) {
// in here, get your principal, and populate the auth object with
// the right authorities
Authentication auth = doAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(auth);
}
chain.doFilter(request, response);
}
Yes, it's possible. Spring Security (like most of the rest of Spring) is interface-driven so that you can plug in your own implementations selectively for different parts of the framework.
Update: Spring's authorisation and authentication mechanisms work together - the authentication mechanism will authenticate the user and insert various GrantedAuthority instances in the security context. These will then be checked by the authorisation machinery to allow/disallow certain operations.
Use nont's answer for the details on how to use pre-existing authentication. The details of how you get the details from your session (e.g. roles ) will of course depend on your specific setup. But if you put in the GrantedAuthority instances derived from the roles pre-populated in your session by your SSO system, you will be able to use them in your authorisation logic.
From the reference documentation (slightly edited, with my emphasis):
You can (and many users do) write
their own filters or MVC controllers
to provide interoperability with
authentication systems that are not
based on Spring Security. For example,
you might be using Container Managed
Authentication which makes the current
user available from a ThreadLocal or
JNDI location. Or you might work for a
company that has a legacy proprietary
authentication system, which is a
corporate "standard" over which you
have little control. In such
situations it's quite easy to get
Spring Security to work, and still
provide authorization capabilities.
All you need to do is write a filter
(or equivalent) that reads the
third-party user information from a
location, build an Spring
Security-specific Authentication
object, and put it onto the
SecurityContextHolder. It's quite easy
to do this, and it is a
fully-supported integration approach.
The server that handles the authentication should redirect the user to the application passing to it some kind of key (a token in CAS SSO). Then the application use the key to ask to the authentication server the username and roles associated. With this info create a security context that is passed to the authorization manager. This is a very simplified version of a SSO login workflow.
Take a look to CAS SSO and CAS 2 Architecture.
Tell me if you need more information.
we have had the same requirement where we had to use spring security for authorization purpose only. We were using Siteminder for authentication. You can find more details on how to use authorization part of spring security not authentication here at http://codersatwork.wordpress.com/2010/02/13/use-spring-security-for-authorization-only-not-for-authentication/
I have also added source code and test cases at http://code.google.com/p/spring-security-with-authorization-only/source/browse/
I am trying to understand CAS authentication with our own Authorization and was getting confused since the User object in Spring Security always expects the password to be filled in and we don't care about that in our scenario. After reading Surabh's post, it seems that the trick is to return a custom User object without the password filled in. I will try that out and see if it works in my case. Hopefully no other code in the chain will be expecting the Password in the User object.
I use the authorization by this:
Inject the authorization related bean into my own bean:
#Autowired
private AccessDecisionManager accessDecisionManager;
#Autowired
FilterSecurityInterceptor filterSecurityInterceptor;
Use this bean by this:
FilterInvocation fi = new FilterInvocation(rundata.getRequest(), rundata.getResponse(), new FilterChain() {
public void doFilter(ServletRequest arg0, ServletResponse arg1) throws IOException, ServletException {
// TODO Auto-generated method stub
}
});
FilterInvocationDefinitionSource objectDefinitionSource = filterSecurityInterceptor.getObjectDefinitionSource();
ConfigAttributeDefinition attr = objectDefinitionSource.getAttributes(fi);
Authentication authenticated = new Authentication() {
...........
public GrantedAuthority[] getAuthorities() {
GrantedAuthority[] result = new GrantedAuthority[1];
result[0] = new GrantedAuthorityImpl("ROLE_USER");
return result;
}
};
accessDecisionManager.decide(authenticated, fi, attr);
I too did spent lot of hours investigating on how to implement custom authorization without authentication.
The authentication process is external to our system (based on single sign-on).
I have done it, as mentioned below and it Works!!! (I am sure there are many other ways to it better, but this way just suits my scenario well enough)
Scenario : User is already authenticated by external system and all information needed for authorization is present in the request
1.
Security config need to be created, enabling global method security as below.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class SpringWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
}
}
2.) Implement Spring PermissionEvaluator to authorize whether the request should be allowed or rejected
#Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
public boolean authorize(final String groups, final String role) {
boolean allowed = false;
System.out.println("Authorizing: " + groups + "...");
if (groups.contains(role)) {
allowed = true;
System.out.println(" authorized!");
}
return allowed;
};
#Override
public boolean hasPermission(final Authentication authentication, final Object groups, final Object role) {
return authorize((String) groups, (String) role);
};
#Override
public boolean hasPermission(final Authentication authentication, final Serializable targetId, final String targetType, final Object permission) {
return authorize((String) targetId, (String) permission);
};
}
3.) Add MethodSecurityConfig
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
}
4.) Add #PreAuthorize in your controller as shown below. In this example, all the groups of the user are present in request header with key 'availableUserGroups'.
This is then passed on to the CustomPermissionEvaluator to verify authorization. Please note that spring automatically passes Authentication object to the method 'hasPermission'.
So in case if you want to load user and check using spring 'hasRole' method, then this can be used.
#PreAuthorize("hasPermission(#userGroups, 'ADMIN')")
#RequestMapping(value = "/getSomething")
public String getSomething(#RequestHeader(name = "availableUserGroups") final String userGroups) {
return "resource allowed to access";
}
Handling Other Scenarios :
1.) In scenario where you want to load the user before you can perform the authorization. You can use spring pre-authentication filters, and do it in a similar way.
Example link : http://www.learningthegoodstuff.com/2014/12/spring-security-pre-authentication-and.html