ASP.NET WebAPI Security 4: Examples for various Authentication Scenarios

The Thinktecture.IdentityModel.Http repository includes a number of samples for the various authentication scenarios.

All the clients follow a basic pattern:

  1. Acquire client credential (a single token, multiple tokens, username/password).
  2. Call Service.

The service simply enumerates the claims it finds on the request and returns them to the client. I won’t show that part of the code, but rather focus on the step 1 and 2.

Basic Authentication
This is the most basic (pun inteneded) scenario. My library contains a class that can create the Basic Authentication header value. Simply set username and password and you are good to go.

var client = new HttpClient { BaseAddress = _baseAddress };
client.DefaultRequestHeaders.Authorization =
new BasicAuthenticationHeaderValue("alice", "alice"
);

var response = client.GetAsync("identity").Result;
response.EnsureSuccessStatusCode();

 

SAML Authentication
To integrate a Web API with an existing enterprise identity provider like ADFS, you can use SAML tokens. This is certainly not the most efficient way of calling a “lightweight service” ;) But very useful if that’s what it takes to get the job done.

private static string GetIdentityToken()
{

   
var factory = new WSTrustChannelFactory
(
       
new WindowsWSTrustBinding(SecurityMode
.Transport),
        _idpEndpoint);
    factory.TrustVersion =
TrustVersion
.WSTrust13;

   
var rst = new RequestSecurityToken
    {
        RequestType =
RequestTypes
.Issue,
        KeyType =
KeyTypes
.Bearer,
        AppliesTo = new EndpointAddress(Constants
.Realm)
    };

   
var token = factory.CreateChannel().Issue(rst) as GenericXmlSecurityToken
;
   
return
token.TokenXml.OuterXml;
}

private static Identity CallService(string
saml)
{
    var client = new HttpClient { BaseAddress = _baseAddress };
    client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("SAML"
, saml);

   
var response = client.GetAsync("identity"
).Result;
    response.EnsureSuccessStatusCode();

   
return response.Content.ReadAsAsync<Identity>().Result;
}

 

SAML to SWT conversion using the Azure Access Control Service
Another possible options for integrating SAML based identity providers is to use an intermediary service that allows converting the SAML token to the more compact SWT (Simple Web Token) format. This way you only need to roundtrip the SAML once and can use the SWT afterwards.

The code for the conversion uses the ACS OAuth2 endpoint. The OAuth2Client class is part of my library.

private static string GetServiceTokenOAuth2(string samlToken)
{

   
var client = new OAuth2Client
(_acsOAuth2Endpoint);
   
return
client.RequestAccessTokenAssertion(
        samlToken,
       
SecurityTokenTypes
.Saml2TokenProfile11,
       
Constants.Realm).AccessToken; }

 

SWT Authentication
When you have an identity provider that directly supports a (simple) web token, you can acquire the token directly without the conversion step. Thinktecture.IdentityServer e.g. supports the OAuth2 resource owner credential profile to issue SWT tokens.

private static string GetIdentityToken()
{
    var client = new OAuth2Client(_oauth2Address);
   
var response = client.RequestAccessTokenUserName("bob", "abc!123", Constants
.Realm);

   
return
response.AccessToken;
}

private static Identity CallService(string
swt)
{
    var client = new HttpClient { BaseAddress = _baseAddress };
    client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer"
, swt);

   
var response = client.GetAsync("identity"
).Result;
    response.EnsureSuccessStatusCode();

   
return response.Content.ReadAsAsync<Identity>().Result;
}

 

So you can see that it’s pretty straightforward to implement various authentication scenarios using WebAPI and my authentication library. Stay tuned for more client samples!

This entry was posted in IdentityModel, WebAPI. Bookmark the permalink.

8 Responses to ASP.NET WebAPI Security 4: Examples for various Authentication Scenarios

  1. Jean-Paul Smit says:

    The link to the repository on github doesn’t work anymore, could you update it?

  2. Pingback: Securing Web API REST services with ADFS and ACS

  3. hoggeek says:

    I have found like 40,000 examples of how to implement the client in this scenario, but precious few that articulate the service site, authenticating the incoming token. I’m successfully calling ADFS, then ACS, and setting the resulting token in an Authorization header with WRAP per some of your samples, but I cannot get Azure configured with ACS to recognize and authenticate the incoming service call. ACS/ADFS browser (passive) clients work just fine.

    Could somebody please pass along the magic sauce for what the other side of this article looks like? The few I find talking about it are either jumping through hoops with 3.5, or casually reference it as, “…and then you call the service, and voila!”

  4. Stephen Cossgrove says:

    Hi,

    I have implemented the ThinkTecture Identity server and everything is fine when i go between website however i cannot for the life of me get the back end calls to work.

    I can get the Security token as discussed above using the WSTrustClient class but I cannot then use this token to call an asmx webservice without getting challenged by the identity server.

    here is my code:
    var saml = genericToken.TokenXml.OuterXml;

    string url = “http://localhost/crm/services/CustomerServices.asmx/PingCRM”;
    url.ConsoleYellow();

    var client = new HttpClient { BaseAddress = new Uri(url) };
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(“SAML”, saml);

    var response = client.GetAsync(“identity”).Result;
    response.EnsureSuccessStatusCode();

  5. satish says:

    Secure 2 different web applications with one identify service

    Identity Service: Thinktecture Identity Service V2
    Application 1: Asp.net MVC 5 application
    Application 2: Asp.net Web API application

    The above Applcation 1 and Application 2 are different projects and hosted in different servers. Now my scenarios are
    1. Want to secure Application 1 with Identity Service.
    2. Want to secure Application 2 with Identity Service.

    Use case 1: If user access Application 1 it should redirect to identity service login page, once I entered the credentials and login in to application 1, the same token allow me to access Application 2.
    Use case 2: If user try to access any API from Application 2 without login into Identity service, the request should reject.

Leave a comment