WCF4 REST APIkey question - pass information from ServiceAuthorizationManager to services - wcf

I want to implement an API key authentication solution for my WCF4 REST API.
I know that I need to make a class and derive it from ServiceAuthorizationManager and override the CheckAccessCore method. All that I understand.
But what I want to do from the CheckAccessCore pass internal information from the CheckAccessCore to my Service implementation classes. Information like "ApiKeyID, rights, flags and other details" that I looked up when doing the ApiKey authentication.
So that my services internally can use the internal ApiKeyID when it calls the domain logic.
I have seen many different ways of doing this, like
operationContext.ServiceSecurityContext.AuthorizationContext.Properties["Principal"] = p;
or
System.Threading.Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
and other ways....

Another way you can pass along objects is by adding the object to the Properties Collection of the RequestMessage object.
IssuedToken Token = new IssuedToken()
operationContext.RequestContext.RequestMessage.Properties.Add("NameOfObj",Token);

Related

Scribe OAuth2 where Endpoints are variable eg: Shopify

I am building an app where I use Scribe for all my oauth needs. I create a service API class overriding DefaultApi20 with my end points for authorization and token URLs.
However for Shopify, the authorization URL is dependent on another parameter (Eg: shop name) where the authorization url needs shopname as subdomain. How do I send parameters for this?
I can do the oauth manually constructing the auth url and token but I am looking for a better way to construct sending custom parameters.
Thanks.
We had a similar situation where a variable on the API had to set differently for different users. We did the following:
-Created a custom serviceImpl which extended OAuth10aServiceImpl (may be OAuth20ServiceImpl in your case).
-gave it a method to set the variable on it's api class
-after service is created by your ServiceBuilder lookup the appropriate value and call the setter method of the service.
-continue with normal OAUth token flow
Note that you also need to let the API know to use the custom service class, for example:
#Override
OAuthService createService(OAuthConfig config)
{
return new CustomServiceImpl(this,config)
}
Hope that helps

Accessing user name in IDispatchMessageInspector

I've implemented custom logging logic for WCF service by using IDispatchMessageInspector.
I'm logging entire SOAP request/response in the database by utilizing both AfterReceiveRequest and BeforeSendReply.
I'm using claims-based authentication which works without any issues.
However, when I attempt to access Thread.CurrentPrincipal.Identity.Name or ClaimsPrincipal.Current.Identity.Name, I get empty string always (identity is not set, thus name is blank).
Is there a way to access the identity in any way from IDispatchMessageInspector?
Thank you!
If your claim-based authentication is working, you could add the user to your claimset.
You can access your ClaimSet in a static way:
ReadOnlyCollection<ClaimSet> claimSets = ServiceSecurityContext.Current.AuthorizationContext;`
The other possibility is adding a ServiceAuthorizationManager to your service, register it in your configuration and access your ClaimSet from this class.
Hope this helps

Windows authentication and Asp.Net Web API

I have an Intranet application with Windows authentication based on MVC4.
When I need the WindowsIdentity for authorization purpose in a Controller I just use
HttpContext.User.Identity
Now I wanted to use the new Asp.Net WebAPI for some Ajax calls.
Is there a way to get the WindowsIdenty object in the same easy way as in an MVC Controller?
Please don't reference the HttpContext from a controller.
You can access the Controllers User property which is way of accessing the Identity through without a dirrect reference to HttpContext.
public class MyController : ApiController
{
public string Get()
{
var indenty = this.User.Identity;
}
}
Why
The controllers User property provides a level of abstraction which allows for easier mocking and thus unit testing. This abstraction also allows for greater portability e.g. if this was WebApi Self Host you wouldn't even have access to HttpContext.
To read more about how to unit test and mock the User property read here. For more information re: portability read here.

How do I do username/password authentication in WCF, with session affinity?

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.

How to store custom information in SecurityContext of spring-security?

In my application I'm using LDAP authentication. But i'm also have 2 remote services which requires authentication via method login(username, password). The method returns security token which makes me able to invoke another methods, i.e. I should pass security token to service methods as first argument.
So I'd like to get these security tokens immediately after successful login using LDAP and store them in SecurityContext. I tried to use authentication-success-handler-ref of form-login element. Using the handler I replace Authentication object in the SecurityContext with custom AuthenticationToken that holds not only password but also security tokens. But in this case I have an exception that no authentication provider supports this class of token.
I know it's also possible to store tokens in the HTTP session but in this case I have to pass session to service object, so I'd like to store the tokens in SecurityContext.
What is the best approach to handle service security token?
I often use the Authentication.getDetails() object to store additional info that may not be directly linked to the user per say. So you can store any object you want in that field (a HashMap for instance) and it shares the Authentication object life cycle.
HashMap<String, Object> info = new HashMap<String, Object>();
info.put("extraInfo", "info");
auth.setDetails(info);
...
Map<String, Object> i = (Map<String, Object>)SecurityContextHolder.getContext().getAuthentication.getDetails();
Your implementation of 'UserDetails' may hold any additional data. This is what gets stored in the SecurityContext which is later accessible after successful login.
You can later access it as (Assumes MyUserDetails implements UserDetails)
Object principal = SecurityContextHolder.getContext().getAuthentication();
if (principal instanceof MyUserDetails) {
MyUserDetails mud = (MyUserDetails) principal;
mud.getMyData(); //Extract your additional data here
}