Skip to content

Getting JSON web tokens (JWTs) from ADFS via Thinktecture IdentityServer’s ADFS Integration

April 14, 2013

Dominick and I recently added three features to IdentityServer that collectively we call “ADFS Integration”. This “ADFS Integration” is a new protocol (which can be enabled, disabled and configured like any other protocol IdentityServer supports). In short this new protocol helps obtain JWTs (indirectly) from ADFS (or really any WS-Trust enabled STS). I’ll describe the three use cases here and how we provide a solution for each:

Scenario #1 — Converting SAML to JWT for delegation-like use:

Imagine you’re building a website that authenticates users by accepting SAML tokens from an ADFS STS that your app trusts (standard WS-Fed). Your app then wants to invoke a WebAPI using the end-user’s identity (a delegation-like scenario). The WebAPI trusts ADFS and wants to leverage all the features of ADFS in producing the token for the WebAPI (such as the authorization rules, claims issuance rules, etc.), but the WebAPI only wants to accept JWTs. How does your web app get a JWT from ADFS for the WebAPI?

If the WebAPI accepted SAML tokens, then this wouldn’t be a problem — the web app would just use WS-Trust and obtain a delegation token directly from ADFS for the WebAPI. But the main obstacle is the JWT requirement.

Solution #1 — IdentityServer’s ADFS SAML authentication:

IdentityServer now supports a new ADFS integration endpoint which can be used to obtain a JWT from a SAML token. For the above scenario, the web application would need to preserve the original SAML token via WIF’s “maintain bootstrap token option”. The web app would then contact the ADFS integration endpoint in IdentityServer passing the SAML token and the realm for which it requires a delegation token (this would be the realm identifier for the WebAPI). IdentityServer would then do the necessary calls to ADFS to obtain a new SAML token for the WebAPI and then IdentityServer will finally convert the SAML token into a JWT and return it to the web application. The web application can then use that as the token when invoking the WebAPI.

For this magic to happen, there is some configuration required in ADFS. First, IdentityServer needs to be configured as a claims provider trust. Second, the WebAPI needs to be configured as a relying party. But with those two configuration settings (and any other rules related to authorization and claims desired) you are really just using the normal features of ADFS to create the token for the WebAPI.

As far as implementation details, essentially IdentityServer is using the bootstrap token to create its own token for the user (as a claims provider trust). It then calls the normal WS-Trust federation endpoints to have ADFS create a token for the WebAPI RP using the token from IdentityServer as the authentication mechanism. So, this isn’t truly creating a delegation token in the sense that the delegation chain is maintained, but the token can be used like a delegation token to pass the end-user’s identity to downstream relying parties.

The configuration needed in IdentityServer for this solution looks as follows:

SAMLAuthenticationYou need to:

  • Enable the ADFS Integration protocol
  • Enable the SAML authentication option
  • Indicate a token lifetime
  • Disable the Pass-thru authentication token option (otherwise SAML will be returned not JWT)
  • Indicate the ADFS federation endpoint (the mixed/symmetric/basic256 WS-Trust endpoint)
  • Indicate the ADFS identifier
  • Indicate the ADFS signing certificate thumbprint
  • Indicate the ADFS encryption certificate

Scenario #2 —Converting JWT to JWT for delegation-like use:

Now imagine you’re building the WebAPI application being invoked from the web app mentioned above. You’ve received a JWT that authenticates the user (and it’s audience is for your application), but you then want to invoke a second WebAPI delegating the user’s identity. We have almost the same problem as above – the second WebAPI wants ADFS to produce the token but wants it in JWT form. The only difference in this scenario is that the app has a JWT for the user and not a SAML token.

Solution #2 — IdentityServer’s ADFS JWT authentication:

The solution here is almost identical to the solution above. The ADFS integration endpoint can accept a SAML token (as described above) but it will also accept a JWT. So really this one endpoint solves both scenario #1 and scenario #2.

In IdentityServer the same configuration would be needed as above, except you would also need to enabled the “Enable JWT authentication” option.

Scenario #3 — Obtaining JWT for AD users from a native/mobile app:

Imagine you’re building a native mobile application (iOS, Android, etc.) for your company and it needs to invoke a WebAPI with the user’s identity. Same as above, the WebAPI want ADFS to produce the token but wants it in JWT form. These mobile platforms don’t have native AD authentication or WS-Trust libraries and yet need some means to authenticate the user and get a JWT for the WebAPI.

Solution #3 — IdentityServer’s ADFS password authentication:

The final credential type that the ADFS integration endpoint supports is username and password. The native application will collect the user’s credentials and, similar to the other two scenarios,  it will pass to IdentityServer those credentials and the realm identifier for the WebAPI it wants to invoke. IdentityServer will contact ADFS and return a JWT to the native app. The native app can use that as the token when calling the WebAPI.

If this last scenario is all you needed, then the minimal configuration needed in IdentityServer would be this:

PasswordAuthenticationYou need to:

  • Enable the ADFS Integration protocol
  • Enable the password authentication option
  • Indicate a token lifetime
  • Disable the Pass-thru authentication token option (otherwise SAML will be returned not JWT)
  • Indicate the ADFS username endpoint (the username/mixed WS-Trust endpoint)
  • Indicate the ADFS signing certificate thumbprint

The one last thing I’ll say after this new ADFS integration feature — when IdentityServer converts a SAML token from ADFS into a JWT it is signing the JWT with its signing key. So this means that the signing thumbprint all the relying parties trust need to be that of IdentityServer. This might be different than the signing key of ADFS, or it could be the same — this configuration choice would be up to you. But this is a detail that is important to be aware of.

There are two samples that illustrate exercising these endpoints. First there’s a sample that just invokes the endpoints and second there’s a more full fledged sample that illustrates the real flow through the web application and then to two downstream relying party WebAPI apps.

Feedback welcome and enjoy!

42 Comments leave one →
  1. April 15, 2013 2:37 am

    Reblogged this on http://www.leastprivilege.com and commented:
    This can be very handy when having to integrate web APIs / mobile devices with ADFS!

  2. April 25, 2013 10:43 am

    A beginners question (and I hope it is not too inappropriate here): I have an existing Exchange server with users, and I want my Thinktecture server to use that information when users log in. How do I connect the Exchange server and the Thinktecture server? Are there any tutorials out there?

    • April 25, 2013 10:49 am

      Re: tutorials — not that I’m aware of. As for achieving this, you’d need to extend IdentityServer and write the code to validate credentials against exchange (if exchange even exposes such a credentials validation API).

      • danielbsig permalink
        April 25, 2013 12:53 pm

        OK, what I REALLY meant is that I have my users in Active Directory :-) sorry about that!

        • April 25, 2013 12:55 pm

          So then you can configure IdentityServer to use the AD membership provider, or you can code an extensibility point in IdentityServer to do LDAP calls to AD to validate credentials.

          • danielbsig permalink
            April 25, 2013 1:02 pm

            AD Membership Provider -> would that involve ADFS? Are there tutorials which show how that is done?

            Also: thanks for answering these beginners questions! I really appreciate it.

          • April 29, 2013 9:31 am

            AD membership provider is a ASP.NET provider that will do username/password checks against a LDAP (AD) server. It’s a Microsoft API.

  3. utsav permalink
    April 29, 2013 2:49 am

    Hi , I am using Think Tecture Identity Model in my project but i am facing a issue. This is because the DLL which i am using is not referenced. How can i resolve this issue. please help me onm the same.
    Error 1 “The type ‘System.IdentityModel.Tokens.SecurityToken’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089’

    • April 29, 2013 9:32 am

      That’s an assembly that’s from .NET 4.5. Just add it as a reference in your project.

  4. May 2, 2013 12:56 pm

    Maybe slightly off topic…but here goes…
    I am using Thinktecture.IdentityModel45 in a WebAPI.
    My customer wishes for the mobile clients to authenticate with their ADFS. Is this a supported scenario?

  5. May 7, 2013 8:51 am

    Firstly can’t say thank you enough, secondly in solution 1 you mentioned adfs configuration, any pointers on how to get adfs to give saml 2.0 assertion tokens? all I am getting is saml 1.0. missing something fundamental.

    • May 7, 2013 10:26 am

      Yea, I have seen that before where for WS-Fed ADFS only wants to issue SAML 1.0 tokens, but for SAML2-P requests it issues SAML 2.0 tokens. I don’t know off the top of my head, sorry. If you find out, please follow-up here :)

    • Eduardo Bonato permalink
      May 25, 2013 7:57 pm

      Which ADFS version are you using? AFAIK, only ADFS 2.0 is able asserts SAML 2.0 tokens. You can look at http://msdn.microsoft.com/en-us/magazine/ee335705.aspx

      • May 27, 2013 8:57 am

        I have verified that it was ADFS 2.0, but the issue in the end wasn’t Saml Token version, but rather the configured ADFS Issuer Name, I thought it was https://…. but turns out the default name is http:// this tripped me up for days, but lesson learned new assume anything…

  6. Himanshu permalink
    May 29, 2013 11:50 am

    Is it possible to do the ADFS integration without using Identity Server, As John asked earlier can this be achieved using Thinktecture.IdentityModel45 only.

    • May 29, 2013 12:01 pm

      If the client can use WS-Trust directly to the ADFS server, then yes.

  7. John K permalink
    May 30, 2013 8:35 pm

    We have a custom STS that is implemented using WIF. When a RP authenticates with IdentityServer it delegates the authentication to our STS using Home Realm Discovery. Is there any info on how to implement the ADFS integration protocol in our STS? Can WIF help me here?

    We are looking to implement scenario #3 with our custom STS in the place of ADFS.

    • May 31, 2013 1:24 am

      Sure, as long as your custom STS supports WS-Trust (like ADFS does) then you should be all set.

  8. Prasad permalink
    June 11, 2013 2:18 am

    Hi allen,We are getting SAML token from IP-STS and at RP-STS we would like to convert SAML to JWT token then passing JWT token to Resource Provider.we are facing problems how to pass JWT token to Resource Provider apart from this we did everything.At RP we are using Thinktecture.will you please give any guidance ?

  9. Prasad permalink
    June 12, 2013 2:39 am

    Thanks for the reply we are using ASP web applications not web api, At RP we are using thinktecture only to generate jwt token.we are not able to find out the way to pass jwt token

  10. Ravi Ponnuru permalink
    June 13, 2013 11:48 pm

    In the images that you posted I see that you have ADFS Integration in the protocols section, but I don’t see that in my thinktecture server 2. Am I missing something?

  11. Ravi Ponnuru permalink
    June 14, 2013 12:09 am

    Makes sense. I think I downloaded the release version from the website, not the github version.

    Thank you.

  12. June 26, 2013 9:11 pm

    I am trying to implement the Scenario#3 with mobile app as an .ajax client and I want to use ADFS as an Identity Provider since all our applications are integrated with ADFS.
    Here are my Applications.
    1. Mobile (ajax) Client
    2. ADFS (as an identity provider)
    3. IdentityServer
    4. WebAPI
    Here is my configuration so far.
    1. ADFS has been added as an Identity Provider in Thinktecture Server
    2. ADFS Integration has been enabled in the Protocols in the Thinktecture Server
    3. Thinktecutre has been added as a Relying Party in ADFS
    4. WebAPI has been added as a relying party to the Thinktecture Server

    Now I am trying to get a JWT token from the Thinktecture Server using Adfs integration protocol with an ajax request.
    Here are my questions.
    1. Am I doing or missing anything so far.
    2. How do I make an ajax call with username/password. Is there an example?

    • June 27, 2013 12:08 am

      IdentityServer needs to be configured as a claims provider trust in ADFS and the WebAPI needs to be configured as a RP in ADFS. Read the readme in here for more details:

      https://github.com/thinktecture/Thinktecture.IdentityServer.v2/tree/master/samples/AdfsIntegrationFullSample

      Also, scenario #3 is describing a native mobile application, not a browser-based JavaScript client. But I suppose you could get it to work — you’d just need to enable CORS in IdentityServer to allow the cross-origin calls from the JavaScript client. But this wasn’t the scenario we designed for.

      But in reality, if you’re using a JavaScript based client and are looking for a token for a WebAPI then you might want to look into the OAuth2 Implicit Flow instead — this would be the preferred protocol. The new Thinktectecture AuthorizationServer is meant to be a full fledged OAuth2 authorization server implementation and you can federated with ADFS (or IdentityServer) for users to authenticate. Here’s the project link:

      https://github.com/thinktecture/Thinktecture.AuthorizationServer

  13. July 16, 2013 11:13 am

    Hi which version of the server is this?

    I don’t see a lot of those options including Identity Providers. I just got the 2.2.1 release.

    • July 16, 2013 2:21 pm

      It’s in the source code repo on github. Not sure which release contains this, tho. You’d have to check the check in history (we don’t do a great job with labeling).

  14. September 16, 2013 4:10 pm

    thanks you for that article ,its so useful , i have windows server 2012 virtual image with adfs 1.1 , is that can be configured as SSO with MVC 4 as relying party?, or i need to install ADFS 2.0 or ADFS 2.1, actually i got error while setting the trust between adfs 1.1 and my MVC app, the ADFS not supporting the metadata file in my MVC app,
    also pls could you provide link or advise me how can i upgrade the adfs 1.1 to adfs 2.0?

    thank you so much

    • September 22, 2013 7:31 am

      If you have issues then open them on the github issue tracker, please.

  15. Sharad permalink
    May 13, 2014 11:22 am

    Hi,

    Thanks for the article. Also would like to extend thanks to both you and Dominick for making our lives easy.

    I would like to set up Thinktecture identity server as a STS layer above ADFS STS service.
    Our parent company has multiple sub-companies let’s say ‘ABC’ and ‘XYZ’ for example. Also, they have some common set of applications that are used across all the sub-companies.
    The vision is that users from these different domains example user_1@abc.com and another user_2@xyz.com (not in the same forest) can access the same application by authenticating against their individual Active Directory accounts itself.
    To support this I would like to set up Thinktecture identity server as a STS layer above individual ADFS STS services deployed for the different active directories on their individual AD servers.
    This identity server STS layer will act as the single interface to which the claims aware relying party application will bind to for authentication.
    Internally, when Thinktecture identity server receives the authentication request, it can federate the request to relevant ADFS based on whether the domain was ‘abc.com’ or ‘xyz.com’

    I already have set up Identity server and ADFS as well and have 2 claims aware applications successfully authenticating from them individually.
    How do you suggest to configure the Thinktecture identity server above the ADFS services?

    I have looked at some of your videos http://vimeo.com/51666379 and the above article; done the steps but not able to get this to work. Any help would be highly appreciated especially since I am fairly new to Claims world.

    Thanks
    Sharad

    • May 14, 2014 11:20 am

      Check the wiki on github — it has links to more info on setting up IdentityServer.

      • Sharad permalink
        May 15, 2014 8:38 am

        Hi Brock,

        As mentioned in my original comment, I have already set up the identity server successfully.
        I am also able to successfully authenticate from the AD through /issue/hrd home realm discovery but not getting redirected back to my claims aware application. The AD redirects me back to the identity server only.
        I have configured Thinktectureidentityserver as a Relying party in my ADFS and provided the home page url as the redirect url in adfs.
        I believe the one thing that might be wrong could be something in the configuration for Thinktectureidentityserver added as a relying party in ADFS. The video http://vimeo.com/51666379 also does not show anything about the configuration.

        What am I doing wrong?

        I found on Googling that many others users are also facing similar issue. and all are asking for the same question: How to add Thinktectureidentityserver as a relying party in the ADFS.

        Thanks
        Sharad

        • May 15, 2014 11:22 am

          So make sure the hrd endpoint is the one configured in ADFS as the redirect URL (which I assume you have). If it is, then perhaps this is a bug in IDSvr. If you think so then submit it to the github issue tracker, please.

  16. Sharad permalink
    May 14, 2014 11:10 am

    Hi,

    As a follow up to my previous comment, I am able to successfully authenticate from the AD through /issue/hrd home realm discovery but not getting redirected back to my claims aware application. The AD redirects me back to the identity server only.
    I have configured Thinktectureidentityserver as a Relying party in my ADFS and provided the home page url as the redirect url in adfs.
    I believe the one thing that might be wrong could be something in the configuration for Thinktectureidentityserver added as a relying party in ADFS. The video http://vimeo.com/51666379 also does not show anything about the configuration.

    What am I doing wrong?

    I found on Googling that many others users are also facing similar issue. and all are asking for the same question: How to add Thinktectureidentityserver as a relying party in the ADFS.

    Thanks
    Sharad

  17. February 3, 2015 8:59 pm

    Hi I have watched You on pluralsight (it was excelent transfer of knowledge)
    What is the right way to do this without ADFS.
    I want to transform SAML2 token that I got in MVC app (held via WIF’s bootstrap token) into JWT in order to call Web API from MVC

    Web api is configured like in sample https://github.com/IdentityServer/Thinktecture.IdentityServer2/tree/master/samples/AdfsIntegrationFullSample

    Thanks in advance

  18. February 3, 2015 9:04 pm

    Hi
    What is the right way to do this without ADFS.

    I got SAML token in MVC app (held via WIF’s bootstrap token) and now I want to get JWT to call API like in example

    https://github.com/IdentityServer/Thinktecture.IdentityServer2/tree/master/samples/AdfsIntegrationFullSample

    When I follow the example I got 400 Bad Request on line 67
    https://github.com/IdentityServer/Thinktecture.IdentityServer2/blob/master/samples/AdfsIntegrationFullSample/MsftJwtIdentityModelExtensions/AdfsIntegrationProxy.cs

    Thanks in advance

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: