OWIN security components in ASP.NET: OpenID Connect!

OWIN security components in ASP.NET: OpenID Connect!

  • Comments 13

It’s been about a month since we released the first preview of the new claims-based identity programming model in ASP.NET. Yesterday we published a refresh of the preview with lots of improvements in WS-Federation support, and a brand-new feature: OpenID Connect!

Thanks for the Feedback

The new programming model was very well received, which makes us very happy; however, you were not shy about letting us know which features you wanted us to change and add. I would like to take this opportunity to thank Dominick and Poul for their deep involvement and great feedback!
Among the main points we heard:

  • Ensure that the new components are compatible with the Azure Active Directory OAuth bearer middleware
  • Maintain consistency with well-established conventions in the framework (e.g. support for SignInAsAuthenticationType)
  • Keep the layering which separates pure protocol concepts from the middleware proper

We managed to address all of the above, and more. Besides the inevitable bug fixing, we rearranged the validation pipeline to ensure that every stage receives the info it needs in the notifications; we improved error handling & sign out support; and we verified some notable composite scenarios. Then, we added support for an entirely new protocol Smile

OpenID Connect in ASP.NET and Azure AD!

By now you certainly heard of OpenId Connect, the recently ratified open standard that layers authentication on top of OAuth2 and the JWT token format. For a quick intro see this and this.

Azure Active Directory supported OpenID Connect already for quite some time – every time you sign in the Microsoft Azure portal, that’s what’s you’re using – but we didn’t have support for it in our web programming stack. Well, now we do Smile

image

If you search the NuGet.org feed for “OpenIDConnect” and include prerelease packages, you’ll find a couple of new packages which contain base classes constituting the OpenID Connect primitives and the middleware proper implementing the protocol.

We’ll give more details (far more details) next week, however: if you want to get a taste of how it works, start by following from start to finish the WS-Federation & OWIN tutorial here.

Once you are done, switching from WS-Federation to OpenID Connect is super easy!

  • Install the package Microsoft.Owin.Security.OpenIdConnect (remember, it’s in the prerelease feed)
  • Go to Startup.Auth.cs, and substitute the ConfigureAuth implementation with the following:
public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions { });

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            Client_Id = "d71c88d1-f3d3-47e9-8313-06bc9af9a991",
            Authority = "https://login.windows.net/azurefridays.onmicrosoft.com/"
         }
}

Yes, we did shrink this even further Smile
The most interesting part is the initialization code for the OpenIdConnectAuthenticationOption.

  • Client_Id is the unique identifier assigned to your application by Azure AD at creation time. You’ve been using this value for all OAuth2 flows where the app acted as a client: in OpenId Connect you use it in roughly the same way in which you used the realm in WS-Federation
  • Authority here represent your Azure AD tenant. AAD exposes metadata describing signing key and issuer values to validate, in analogy to what happens for WS-Federation and SAML: the Authority property is just a convenient way for you to refer to that document without knowing its exact address (which BTW is of the form https://login.windows.net/azurefridays.onmicrosoft.com/.well-known/openid-configuration and can be used directly in the MetadataAddress property if you prefer to set it explicitly)

That’s all you need for adding OpenId Connect sign on to your app!

Of course there’s far more that you could do. For example, with OpenId Connect it is very easy to sign in and at the same time obtain an access token for your app to access other APIs (such as the Graph, Office 365, your own, etc) and the new object model makes it very natural. We’ll talk about this and many other scenarios at length next week!

Next

As the boss of my boss of my boss puts it, “Widely-available secure interoperable digital identity is the key to enabling easy-to-use, high-value cloud-based services for the devices and applications that people use. OpenID Connect fills the need for a simple yet flexible and secure identity protocol and also lets people leverage their existing OAuth 2.0 investments. Microsoft is proud to be a key contributor to the development of OpenID Connect, and of doing our part to make it simple to deploy and use digital identity across a wide range of use cases”.

We were very keen to add OpenId Connect support in our web programming stack, and we are doubly excited to do so in the new OWIN security components in ASP.NET. You have been great in giving us feedback during the first preview, we hope you’ll find the time to try the new bits and let us know what you think:

In addition, if next week you happen to be at S.Francisco and you want to chat about this come find us, either on the //BUILD conference floor or at this meetup: we’ll be happy to give more details.

Thanks and enjoy!

Leave a Comment
  • Please add 4 and 6 and type the answer here:
  • Post
  • Hi,

    This is excellent news, however, I've just tried to substitute this for the existing Google OAuth2 middleware, and have the following comments:

    * Lots of properties of OpenIdConnectAuthenticationOptions have underscores in their names, which is very not-dot-net, and is inconsistent with previous Owin middleware options classes.

    * The OpenIdConnect stuff has a dependency on Microsoft.Owin.Security 3.0.0 which doesn't appear to be correctly listed in the nuget package, so the package installs without upgrading Microsoft.Owin.Security (mine was 2.1) and then fails to build.

    * I now have it building, but it's not showing up as an external provider on my login page - i.e. GetOwinContext().Authentication.GetExternalAuthenticationTypes() is not returning it.  I suspect this is some package version/build problem which I haven't found yet...

    Hope this helps - I'll add another comment if I get any further.

  • OK, well, I got a fair bit further.  To have the new middleware show up as an external auth method, it has to have a Caption set on the Description property of the AuthenticationOptions base class.  (The other OWIN middleware does this internally).

    I  srtill can't currently get it to auth with Google though, because they're complaining about "Redirect_Uri" missing, and I can't work out what that's supposed to be to allow the middleware to detect the redirect back from Google.  

    Per the example above, is Azure somehow working without Redirect_Uri set?    (It's supposed to be required from my reading of the specP, and the only way to set it at present is through the Options, at which time you don't get much help from, e.g. MVC routing to work out a proper URL.

  • Will,

    Thanks for the comments.

    We are fixing the dependency issue, shouldn't be long.

    About the underscores, we struggled with that. We landed on the principal of echoing the spec so that users reading the spec wouldn't have to perform any translation. I agree that it seems to break the normal .Net naming, but we felt it was beneficial.

  • Will,

    You can set the Redirect_Uri on the OpenIdConnectAuthenticationOptions, it will get add to the query.

  • Brent - Thanks for the reply - I see where you're coming from with the underscores.

    Yes, I understand that I can set the URI on the options object - what I don't understand is:

    a. What I should set it to (I'm assuming it needs to route back into the middleware, like for example <server>/signon-google does with with the older external auth middleware)?   The xxHandler class doesn't look the same as the other external auth MW does in this regard, and I'm struggling to work out how the reply from the IDP ends up back in the MW.   (Can you tell I'm not good at either OAuth or OWIN...?)

    b. How the Azure AD example in this blog post works without that value being set on the options object?

  • That doesn't make any sense with the underscores. I understand that's how it is in the spec but I seriously doubt anyone who is a .NET developer will "struggle". Actually I expect .NET implementations of third party protocols and frameworks to follow .NET's way of doing things. This is very unappealing and inconsistent with the rest of our application's code.

  • Sorry for the naive question,

    I would like to use OpenId connect to provide my users with a Google+ login option.

    At the same time, this is not enough, as after Google+ authentication I need to validate if the user such identified does indeed exist in our system.

    Do I need to write my own Owin AuthenticationHandler that runs after the OpenId Connect and do the post-processing there?

    Regards,

    Karl

  • Hi Obry, thank you for the feedback. As Brent mentions, this is an area we are still studying. Windows Identity Foundation went through the route of representing protocol parameters using .NET conventions, and during the last few years we got pretty strong feedback that it was making it harder to use for people with knowledge of the protocol. We are trying hard to understand what the most usable solution will be, and all feedback helps.

    Hi Karl, we did not test the middleware against Google+ at this time - but if they support POST and code+id_token you should be able to connect. For what concerns verifying your own ID, check out the sample at github.com/.../WebApp-MultiTenant-OpenIdConnect-DotNet and specifically the SecurityTokenValidated handler in github.com/.../WebApp-MultiTenant-OpenIdConnect-DotNet - we demonstrate exactly what you are mentioning I believe :-)

    Thanks!

    Best,

    V.

  • Hi Vittorio,

    thank you for your response. It helps, but I am not sure my use case is a match.

    Actually I am not sure how OpenID Connect would work with my use case.

    It seems in OpenId Connect the "Client" is the web app, and not the actual client (in the browser).

    However, my "client" is a single page application that does not make requests to the web server except for loading app modules. The rest is done through WebApi calls. Currently it is secured through either Windows or a proprietary Owin authentication handler using legacy login logic (sending back a JWT), all only through interactions with the WebApi.

    I am hoping to maintain that approach, as we also have an Android/Xamarin client that definitely does not show web pages.

    I can sign in the SPA client with Google+ (using openid scope) and get back something like this (parts omitted)

    {

    "state": "",

    "access_token": "...",

    "token_type": "Bearer",

    "expires_in": "3600",

    "code": "...",

    "scope": "www.googleapis.com/.../plus.me",

    "id_token": "...",

    "authuser": "0",

    "num_sessions": "2",

    "session_state": "...",

    "prompt": "none",

    "client_id": "...",

    "g_user_cookie_policy": "single_host_origin",

    "cookie_policy": "single_host_origin",

    "response_type": "code token id_token gsession",

    "issued_at": "1397492204",

    "expires_at": "1397495804",

           ...

    }

    The problem is, I think this is actually what your OpenId Connect middleware would do, instead of the Javascript in the browser. It seems all that authentication interaction is between the web server and the OpenId Connect provider.

    In my limited understanding I thought I could somehow use this id_token like:

    - Send it to WebApi.

    - WebApi validates id_token with Google and gets user details (claims) from Google.

    - WebApi returns an access token.

    But it looks like my use case is not covered?

  • Hi Karl,

    you are correct. As of today, the SPA approach is not supported for organizational accounts. We will be tackling this as soon as the Azure AD endpoints start supporting the OAuth2 implicit flow.

  • Karl,

    As far as I can tell, Google's OIDC implementation doesn't support form_post, so you can't use this middleware to authenticate with Google at present.  (I couldn't anyway!)

    My guess is that Katana will probably have to support alternatives to this anyway if the OIDC middleware is to be more generally useful outside Azure AD, but it's not there yet.

    W

  • Hi Vittorio, Will,

    It seems I can get something working as my use case is simple - I am not interested in delegation of authorization, only in authentication.

    So, the approach is:

    - Authenticate in SPA client using Google's JS libraries - this gets me an authorization code.

    - Pass the code to my WebApi server, where it gets exchanged for an access token.

    - Use the access token to get the users Google id (subject field).

    - Validate Google user id against my database.

    From there on I create the same type of JWT I was using before, and pass it back to the SPA client.

    Karl

  • Hi this is great!

    How would I go about getting the access token back all in one authentication request? What extra configuration do I need to set in my Startup.cs and then how would the token be sent back to my client application? (querystring?)

Page 1 of 1 (13 items)