Was curious if there was a way to check if a user is authenticated before making a method call and then returning a custom object and not completing the call if they aren't. For example:
We set the user principal in the Application_PostAuthenticateRequest in the global.asax to the user making the request if they are authenticated or to an anonymous user if they aren't. Currently in all methods that require authentication we have something similar to the following code:
public Result GetSomeObject()
{
if (HttpContext.Current.Request.IsAuthenticated)
{
}
}
Bottom line: We want to be able to check IsAuthenticated BEFORE we let WCF get inside the method on methods that require authentication, and if true, continue, if not, return a Result object (JSON) with an authentication error.
What you need to develop is called ServiceAuthorizationManager in WCF. You can find more information about this on:
http://pieterderycke.wordpress.com/2011/04/07/implementing-restricted-access-to-a-wcf-service-with-the-serviceauthorizationmanager/
You can write a custom httpmodule to intercept the requests to the service layer and do the authentication in there.
This article may be a starting point for what you are looking for: http://pieterderycke.wordpress.com/2010/12/04/extending-wcf-creating-a-logging-component/
Related
I wrote a UserNamePasswordValidator descendant for validation purpose (basicHttpBinding).
The problem is when I validate a user against back service I receive its identifier that I have to use in service class method. That turns out to be a huge problem... unless you know how to do it ...
Is there another authorization alternative that I will not have to pass userName / password in method header or even worse in method's parameters of the Service?
WCF service authentication and authorization can use UserNamePasswordValidator and IAuthorizationPolicy. Here's an article on how to do it. If not, try using IPrincipal.
I'm working on an AWS project. We want to be able to issue STS temporary security credentials, with limited permissions, in order to access AWS services. We're working in .Net Core with C#.
We're using STS AssumeRoleAsync(), which is the .Net SDK's method for using the AWS AssumeRole action, to generate these credentials. The response from the call to AssumeRoleAsync() is an AssumeRoleResponse object, which is comprised in part of an AssumeRoleUser object and a Credentials object. One of the properties of AssumedRoleUser is AssumedRoleId, which is in the form of role-id:role-session-name.
We have a Lambda function which handles calling AssumeRoleAsync and returning the generated credentials in the form of a JSON object. That Lambda function is called via an API Gateway method.
All of this is working fine. The above was just to set the scene.
The next thing we want to be able to do is to use the STS temporary credentials to make other calls into AWS services. When that happens, we want be able to use GetCallerIdentity() to retrieve the AssumedRoleId for the person to whom the credentials were issued. In particular, the role-session-name is of interest to us.
So to try to accomplish this, I created another Lambda function behind another API Gateway method. I set this API Gateway method to use AWS_IAM authorization in its Method Request configuration. In its Integration Request, I configured it to Invoke with caller credentials. The Lambda function simply accepts the incoming request and calls GetCallerIdentity() and returns the result. I used the credentials returned from the previous AssumeRoleAsync() call in the request's authorization header.
Based on the information found in the docs for GetCallerIdentity and in the Principal Table to which that page refers, I expect to receive the following items in response from the GetCallerIdentity() call:
Account
Arn
UserId (this is the important bit for this discussion)
The UserId should be in the form of role-id:caller-specified-role-name, exactly the same form in which the AssumedRoleId from the call to AssumeRoleAsync was returned. That would allow me to get the caller-specified-role-name and do what we need to do with it.
But that isn't what is returned in the UserId property of the response from GetCallerIdentity().
Instead, all that the UserId property contains is the role-id — it completely omits the essential caller-specified-role-name.
Has anyone else seen this behavior? Am I overlooking something simple? Could this be a bug in the response from GetCallerIdentity?
I'm using the following Amazon SDK components and versions to make these various calls:
Amazon.Lambda.Core/1.0.0
Amazon.Lambda.Serialization.Json/1.1.0
AWSSDK.Core/3.3.14
AWSSDK.Lambda/3.3.6.2
AWSSDK.SecurityToken/3.3.1.9
Thanks for any help you can suggest!
Derek
I am in the process of implementing OAuth 2 on a web API with Microsoft.Owin.Security.Oauth.
I would like to keep the bearer token small and keep private data out of it. To do this, I'd like to store a session ID in it and then fill out the ClaimsIdentity programmatically once the session ID has been received and processed. This would also give me greater flexibility related to how logging out, role changes, and other things can be handled.
This should be a matter of intercepting the right event and adding a delegate. However, I can't find an event that gets fired on my authorization provider, a subclass of "OAuthAuthorizationServerProvider". I thought that "AuthorizeEndpoint" would do it, but it does NOT get fired for API methods decorated with the [Authorize] attribute, even though these methods clearly get checked for a valid bearer token. When I overrode "MatchEndpoint", all I found is that a call to a method that was decorated with [Authorize] showed up with "IsAuthorizeEndpoint" and "IsTokenEndpoint" both set to false. The latter makes sense to me, the former does not.
I am very confused. Can somebody who knows this library tell me what's going on and what I need to do to accomplish this seemingly simple idea?
I think you may be conflating resources marked with the AuthorizeAttribute with the OWIN Authorize endpoint. The AuthorizeEndpoint and TokenEndpoint are setup in the OWIN configuration as receivers for their respective authentication types. The Authorize Endpoint is used for web-base, user-agent authentication and is where you would expect a browser to be redirected should they be unauthorized to access a resource. The token endpoint is used instead for username-password token authentication and refreshing, and is the one you want. Assuming you are assigning both of these within your OWIN startup configuration, the event you may be looking to overload for OnValidateTokenRequest to ensure that your customizations to the token do not cause it to be invalid once the client tries to utilize it again. You would want to do your actual modifications to the token at the OnTokenEndpoint event.
I have WCF service hosted on local IIS under SSL.
It seems to be working with SL client. But I stuck on user authentication.
I have login screen with textboxes for user name and password. Once user click on login button something must happen, but what? I saw a lot of examples where are setting up ClientCredentials is the last step. What I suppose to do if user enter bad credentials?
The exception is throwing after calling some operation. I get not a fault exception I had thrown, but CommunicationException.
public class UserAuthentication : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
{
throw new FaultException("Invalid user name or password");
}
}
Also ClientCredentials became read only after calling some operation. So I have to refresh it some how. I was thinking to replace endpoint behavior, but I'm not sure is it good idea.
So, basically my main question is: "What I suppose to do if user enter bad credentials?"
There are two kinds of authentication when it comes to WCF.
First, you can create authentication that works BEFORE the user gets all the way to your WCF interface. So, if you were using client certificates, User/Password or Forms authentication, these forms of authentication are declared within the WCF endpoint definition. These forms of authentication challenge the user (in effect) before they even get to your ping() function, exposing a WCF authentication event during which you can check the client's credentials. This is good because it can help stop hackers from bombing your WCF service with denial of service attacks since the full request never gets processes without authentication. An example can be found here: http://msdn.microsoft.com/en-us/library/aa354513.aspx.
The other method is more obvious: creating a normal WCF login() function, called by the client, during which the client program hands over the ID/password combination for a commplete check against your database or directory. This method, too, works with or without SSL. This is programmed like any other endpoint function ... nothing special here.
Both methods work with or without SSL. In either case, if the credentials are wrong, you can program the login() or authentication() routine to return any error or message your like, including a regular 401 Unauthorized error.
Today, I implemented a custom authentication provider for my WCF service. It is able to determine if my user is valid or not, just as expected.
So, now I have this class:
public class MyCustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
User apiUser = User.Login(userName, password);
// other logic goes here.
}
}
The behaviour of my application depends on what objects the User can access. So, how can I get my User object from here to my service class? There is no immediately obvious way that I can see, as my service class does not inherit from anything by default, unlike the ASP.NET controllers.
My first instinct is to set up a static parameter in MyCustomValidator and then read it from there, but I suspect that a race condition could occur. Can anyone confirm or deny my suspicions?
And most importantly: Is there a better way to do this? This is the first time I have ever used WCF, so I'm not aware of the best practices involved here.
Thank you for your time.
You want to pass some data from validator to service instance. It is bad because you can't do it. UserNamePasswordValidator is only for validating credentials (user name and password). You don't have access to anything from your validator. It even doesn't see current operation context because it runs in different thread. Using static parameter is not a sloution - as you mentioned it is race condition.
I think you need to implement custom authentication and authorization and it is not easy:
WCF Authorizaton, Custom Authorization, Custom credentials and validation