Using WIF STS tokens with WCF - c#

I have recently finished creating a STS setup and need to expose some WCF service methods on the STS's themselves. So far the login sends a token to the claims provider, the claims provider sets all the clams and then hands the user back down to the front end so that's working fine. I need to implement some WCF functions that need to check that the user has a valid token to trigger the method. I have looked into it and have tried configuring WSFederationHttpBind with little success. It seems to ask the client for a certificate via "Windows cardspace" for some reason and I can't find a way to assign the already produced token with the WCF call from the client. Any pointers in the right direction would be great I've been racking my brains all day and clearly not searching for the right thing!
P.S The STS uses WIF to create/assign the tokens

When you say "It seems to ask the client for a certificate via "Windows cardspace" for some reason" do you mean that when the client calls the service operation you get a UI for CardSpace asking the user to select some credentials?
If so, to suppress this you need to set
channelFactory.Credentials.SupportInteractive = false;

A simple sample is avaialble in the WIF SDK. A slightly more complex one is available here: http://msdn.microsoft.com/en-us/library/ff359113.aspx

Related

Azure B2C One time access to secured API

I have a web app (rest API) on azure, and I have a B2C setup that is securing it, requiring you to be signed in to access the API. This is good, as i wanted the API to be restricted to members. Basically, the entire web app requires authentication, and will prompt you for a sign in.
Heres the problem - my app has users (who have accounts) and clients (who do not have accounts). These clients might receive an email about a new appointment being set up with one of the users - this email should have one or more links/buttons (ie, a button to Confirm appointment, one to Decline, and one to request a reschdeule) and upon clicking this link I would like to update a field in my database via the rest api, so the USER knows the CLIENT's response. The trouble is, since the client wont have an account, I have no idea how I can give them a link they would be allowed to go to, and have the update happen.
I have tried to do a bunch of research - ive looked into AD external identities with a one time passcode - but i cant seem to find any info on how i would actually get this to work for my purposes.
Does anyone know how I might implement this in azure? Is there a way to call to azure form c# to generate a one time authentication that i can encode into a URL or something?
Any thoughts would be greatly appreciated.
Thanks!
You could do an anonymous authentication by using a magic link. The users account won’t even need to live in the directory. The link can be short lived, and potentially one time use. We call it id_token_hint or a magic link.
Sample here
https://github.com/azure-ad-b2c/samples/tree/master/policies/invite
And reference here
https://learn.microsoft.com/en-us/azure/active-directory-b2c/id-token-hint

ADFS Active Authentication .NET 4.5 (Post-WIF)

I have an ASP.NET web application (running on .NET 4.5). It's currently doing forms authentication. We've set up an ADFS 3 server with multiple federations, some internal, some external (customer STSs), and we'd like to configure the web application to use an active authentication model. If I understand it correctly, that means that we will continue to use the login form in my web application, and it will gather credentials from the users, then send a security token request to our ADFS server. The token request would presumably tell ADFS which federation to send the request to. If everything is successful, then I get a token back from ADFS, validate it, and construct a ClaimsPrinciple and go from there.
Now, with that background, the problem I'm running into is how to send the token request to ADFS in .NET 4.5. Every example I've seen, despite being labeled as applicable to .NET 4.5 uses the old UserNameWSTrustBinding class from WIF. This is deprecated and not present in 4.5. Web searches for "UsernameWSTrustBinding 4.5 equivalent" have been fruitless. I've seen one guy construct his own class to duplicate the functionality, but I can't believe this is necessary. I've got a hunch that there is a class here somewhere that I'm supposed to be using for the binding in the WSTrustChannelFactory, but I can't find it. Or, perhaps the entire WSTrustChannelFactory pattern is outdated as well (but then why would it have been included in .NET 4.5)?
Can anyone provide a snippet of code or even shed some light on how you're supposed to go about active authentication in .NET 4.5?
So far my best idea has been to check username in the users cookie (if it exists) or from regular login form when the cookie didn't exist. With that info, I can determine whether it needs to be sent to the IdP or not. In the case that it needs to be sent to the IdP, I can just build a request URL and redirect.
WSFederationAuthenticationModule instance = FederatedAuthentication.WSFederationAuthenticationModule;
SignInRequestMessage request = instance.CreateSignInRequest(Guid.NewGuid().ToString(), instance.Realm, true);
request.AuthenticationType = "urn:federation:authentication:windows";
Response.Redirect(request.WriteQueryString());
Of course, I can tweak that request with the appropriate .HomeRealm value or .AuthenticationType in order to skip the HRD process, and then after that, they'll be sent back to the app authenticated and with a proper claimsidentity.
One reason that this isn't the perfect answer for me is that if the user has never logged in before, or has cookies disabled, and depending on the federation, there's potential for them to have to login twice. That is, once to the app's login form, and once to the ADFS form. That's why I was hoping to be able to send a request programmatically somehow instead of redirecting. That way I could presumably send the username & password that were already collected by the app without having to collect them again at ADFS.
For that reason, I won't mark this as the answer. I'd like to hold out for better.

Does the Salesforce REST API allow only one connection at a time like the SOAP API?

So according to the documentation for the SOAP api for Salesforce, if I log in and start a process that takes 1 minute before I log out, then someone else logs in with the same credentials and begins another process that takes 30 seconds before logout, when the second user logs out, it will kick out the first user as well.
Does the REST api have this issue? Is there a way around it?
The answer of your question is YES, REST Api has the same issue.
From official documentation:
If multiple client applications are logged in using the same user,
they all share the same session. If one of the client applications
calls logout(), it invalidates the session for all the client
applications. Using a different user for each client application makes
it easier to avoid these limits.
The only way that salesforce recommends us to avoid this is creating new users.
You could make your own central service to manage the unique session, and give the active access token to clients, but this approach is away force.com platform solutions.
This is really a session management issue more than any specific API you want to call using that session. that said, you have 2 easy options.
a) don't call logout, just let the sessions expire based on inactivity, that way if the session happens to be shared by 2 different integrations it won't cause a problem.
b) switch to OAuth to do your authentication, and give each integration its own OAuth client/remote access entry. (sessions are not shared between different oauth clients).

What is the best way to send custom ACS Claims across programs?

I've got two programs, a "login" program that uses the a foreign STS (Google, Facebook, etc.) to log the user in and returns the type of security access that user has. I then want to send that information off to a separate program that takes that security access and gives the user privileges based on that.
What is the best way to send that information across?
I've read some things about the Custom Authorization Manager Service, but I'm not sure if that is what I need here. Is it possible to just POST the security info across and the web.config turns that into a claim? Should I be making a new token and sending that?
I am hopelessly lost. If someone could provide a helpful tutorial somewhere on the web, that would be immensely appreciated (as my googling has only turned up long-winded articles that either do much more than I need or much less).
Specific code snippets would make my day.
Thanks!
EDIT: I am trying to avoid making the login system into an STS. But I am starting to feel I need to. Is there some halfway point between STS and relying party? Like a relying party that can generate its own claims?
You have several options:
The simplest one is the ClaimsAuthorizationManager, which might be what you're looking for. http://msdn.microsoft.com/en-us/library/ee748497.aspx The CAM is a step in the ASP.NET authentication pipeline that runs right after your application has validated the security token incoming from ACS. Here is where you define your custom authorization logic, and you can add additional claims to the IClaimsPrincipal that gets delivered to yor application. Instead of centralizing authorization logic in a service, you could for example implement your CAM in a library that's shared accross various relying party applications.
If your authorization rules are simple, i.e., you're not querying any external user attribute store, then one option would be to use ACS claims transformation rules to do this. Then your applications would consume the token issued by ACS directly. http://msdn.microsoft.com/en-us/library/gg185955.aspx
If however your architecture absolutely requires a separate login service that consumes tokens and populates new tokens with user attributes and such, then it will need to be an STS. Building your own STS can be tricky, but there are prefabricated STSes available to do this. If your applications live in an AD domain for example, ADFS 2.0 would be an ideal choice because of it's close integration with AD and ACS, and it's powerful claims transformation capabilities.

Best way to handle WCF message authentication in the cloud (C#)

I've looked to many sources, and found many examples, but none really fit the situation that I hope to take a project to. I am writing a bunch of WCF services, some publicly accessible, others not (server to server), that will allow a fully flexible cloud app that ensures the ability to scale out the service as needed through Azure. I am unsure which way to go with message authentication, as I want to make sure a particular user logged in, can perform different tasks, and prevent others from running those tasks.
Most of what I have seen uses roles or ASP.NET membership. I have my own custom membership users will use to login with, and I don't rely on standard membership providers, or active directory. What is your recommendation? I thought about just creating a token that is created on successful login, that is stored within a cookie, added as a parameter passed into each method, but with some research, I think this might be able to be handled without modifying all my methods.
What are your thoughts?
You can easily implement authentication without needing to manually pass a token into all your functions by using UserNameAuthentication and writing a custom validator - there is a fairly straightforward tutorial here
If you use UserNameAuthentication, you will need to use SSL/HTTPS, which means you'll need to get a server certificate - this is a good idea anyway for most business applications.
At the server side you can get the identity of the current user:
IIdentity wic = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity as IIdentity;
use basic authentication and have the webservice authenticate against your membership store.

Categories