Thursday, July 21, 2016

ADFS : Authentication with .NET Core

This is for Active Directory Federation Services (ADFS / "AD FS") on Server 2016 Technical Preview 5.

The client is built on .NET Core along the lines of AAD : Authentication with .NET Core.

So I built the .NET Core sample as per the post above and then changed the code as per this gist.

I configured ADFS by adding an application group and picking "Standalone Application" and "Server application or Website".

Then:


The Client ID needs to be cut and pasted into appsettings.json as does the secret key that you generate as part of the process.

Note that you have to add "/signin-oidc" to the Redirect URL. I have no idea where this comes from. It must be added somewhere as part of the middleware.

Then I got this error:

Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthClientCredentialAuthenticationException: MSIS9267: No Client credentials found in the request. Client '2c...b7' is configured as a confidential client.

Zero documentation on this and much frustration but then in desperation I added the ClientSecret in the code and suddenly it worked!

I did not do this when I did the other examples e.g. ADFS - Web App and Web API on Server 2016 TP4 ADFS 4.0 and they worked so completely baffled!

Enjoy!

AAD : Authentication with .NET Core

This is for Azure Active Directory (AD) with .NET Core 1.0 and VS 2015 Update 3.

Download the .NET Core files for Windows from Core#windows.

We want to write a web application using .NET Core that authenticates with Azure AD.


Then we want to select a web application and we also "Change Authentication" to "Work and School Accounts" and "Cloud - Single Organization".

Note there is no "on-premises" option using ADFS.


You have to enter your Azure tenant and authenticate and then the project is created together with  an application in Azure AD.

The project structure looks much the same as the normal ASP.NET project created this way wrt. the Controller and Views.

Also the authentication is via OpenID Connect as you would expect.

One difference is that the configurable options are no longer in web.config but rather in appsettings.json.

Also, the tried and tested way we have used for years i.e.

ViewBag.ClaimsIdentity = Thread.CurrentPrincipal.Identity;

no longer compiles. There's tons of discussion around this but you can find the code I used in this gist.

The claims then display in the "Contact" tab in the normal way.

Enjoy!

Monday, July 18, 2016

ADFS : Capacity Planning

This is for Active Directory Federation Services (ADFS / AD FS).

There used to be a useful capacity planning spreadsheet available which disappeared for a while.

It's now back and there's one for Server 2016 (ADFS 4.0) as well .

AD FS Capacity Planning Spreadsheet

AD FS Windows Server 2016 Capacity Planning

Enjoy!

Monday, July 11, 2016

Speaking : Getting organised

I been doing a few presentations lately and doing some co-presenting. Some of this with people with very little speaking experience.

Two tips:

Have a work sheet

Write down all the screens and utilities that you will use and use this to check that all are open and logged in before the presentation starts.

e.g.
  • I'm using Azure so ensure I'm logged into the classic and new portal.
  • I'm using Zoomit so ensure it's opened
  • I'm using VS so ensure it's opened and the correct project is loaded
  • I'm using Notepad++ so ensure it's opened
The audience doesn't want to watch you logging into Azure or trying to find that icon.

Write down what you will demo.

When you are standing up there you will be nervous and you will forget to demo. some stuff.

So write down what you will demo., the order, any pertinent points etc.

Print this out in larger type so you can read it from some distance. Have blank lines between the points.

Good luck.

Enjoy!

Friday, July 08, 2016

AAD : Migrating JWT to claims.

Both AAD and ADFS 4.0 (Server 2016) have support for JWT - normally from OpenID Connect / OAuth but also from WS-Fed (via ADFS).

On the RP side, you get a claims principal that contains some of the information that's in the JWT but it's hard to figure out the relationship.

You can see some of it via Get-ADFSClaimDescription with PowerShell.

e.g.

ClaimType  : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier
IsAccepted : True
IsOffered  : True
IsRequired : False
Name       : Name ID
ShortName  : sub
Notes      : The SAML name identifier of the user


You can see more info. here.

So "sub" in the JWT contains the NameID and this then is transformed to a NameID claim by the middleware.

Enjoy!

AAD : Easy Auth

This is for Azure Active Directory (AD).

"Easy Auth" is what the Authentication / Authorization feature in App Services is called.

The idea behind this is that you can have an Azure website and using this feature you can add authentication to it with a few clicks,

You do not have to use NuGet OWIN packages or anything similar. No code is involved.

Essentially it uses an "agent" feature as per Architecture of Azure App Service Authentication / Authorization. There's a native IIS module that sits outside of your application and all requests are directed through this. If not authenticated then you get redirected to the Azure AD login screen. (Recall that Azure web sites actually run on IIS).

You don't not have to add an application to Azure AD. It's all done for you.

So how does it work?

I used VS 2013.

New Project / ASP.NET Web Application. Ensure MVC is checked.

Click the "Change Authentication" button and select the "No Authentication" radio button.

So now we have a bare-bones project with no built-in authentication.

Now deploy to Azure (there are tons of posts around this so I'll skip the details).

At this point you have a web site - e.g. https://easyauth.azurewebsites.net/.

There is no entry for this in Azure AD.

In the new portal, click on "App Services", then the app service (the web site) and then "Settings".


Select "Authentication / Authorization" as above.


Turn on Authentication. choose "Login with Azure Active Directory" from the drop-down and then click the "Azure Active Directory" authentication provider.



Then select the "Express" setting.

Save out.

Now if you go to the old (classic) portal under "Azure Active Directory" you'll see that you have a new application.

You should be able to navigate to your website and the first thing it should do is ask you to authenticate.

Except - it doesn't!

Back to Mr. Google and I found this: How to configure your App Service application to use Azure Active Directory login.

As per the section: "(Alternative method) Manually configure Azure Active Directory with advanced settings", you need to click the Advanced section (not the Express) and add:

/.auth/login/aad/callback

to the "Reply URL"  in Azure Active Directory. Don't worry about all the stuff about actually creating the application - that's already been done.

And then, lo and behold, it worked!

Enjoy!

Monday, July 04, 2016

Azure B2C : B2C user types

There are a number of ways that you can add a user to Azure Active Directory (AAD) B2C (Business to Consumer).

If you look at the "Users sourced from" column, you'll see:
  • Microsoft Azure Active Directory
  • Microsoft Azure AD (other directory)
  • Microsoft account
"New user in your organization"

Your B2C tenant has a name - something like b2c.onmicrosoft.com.

So this user would have a name like joe.bloggs@b2c.onmicrosoft.com.

However, this type of user would be an admin. They couldn't actually log into B2C as an external user because to do this, they would have to have an email address for the confirmation email during sign-up.

Since B2C users cannot have Office 365 accounts this is not possible.

Basic rule of thumb: If you don't sign-up with B2C, you can't sign-in to an application with B2C.

Another way of looking at this is that there are two use cases:
  • Signing into the B2C tenant - manage.windowsazure.com (for admin. purposes)
  • Signing into an application secured by B2C (to access the application)

 We can look at the user's details using Graph Explorer.

(Plus the contents of the claim).

This type of user would have:

"creationType": null

"mailNickname": "user2"
     
"userPrincipalName": "user2@b2c.onmicrosoft.com"

"User with an existing Microsoft account"

This would be for admin. purposes only.

"User in another Microsoft Azure AD directory"

I've found that you need to have rights to the other directory to do this.

"creationType": "Invitation"

"mailNickname": "user_tenant.onmicrosoft.com#EXT#"

"userPrincipalName": "user_tenant.onmicrosoft.com#EXT#@b2c.onmicrosoft.com"

Again this would be an admin. type thing because when you authenticate you are doing this on another tenant, not on B2C.

"User in partner companies"

If you don't have rights, you can use Azure AD B2B. You import a .csv spreadsheet then each user gets an acceptance email with a link they have to click on.

This has the same sort of parameters as "user in another AD directory" but it has an extra section:

"proxyAddresses": [
        "smtp:user_tenant.onmicrosoft.com#EXT#@b2c.onmicrosoft.com",
        "SMTP:user@tenant.onmicrosoft.com"
      ]

Again this would be an admin. type thing because when you authenticate you are doing this on another tenant, not on B2C.

It's a bit confusing that you can add other users in this way as they can't actually authenticate as B2C users but I suppose this is for admin. purposes?

All the above are created by using the Azure portal.

A normal B2C user does not use this portal. They sign-up to B2C by using the sign-up link in the application e.g. as per Azure AD B2C preview: Build a .NET web app.

You can sign-up as a local user i.e. your credentials are stored in Azure AD in the B2C tenant or you can sign-up using social in which case some attributes are stored in the tenant but not the credentials.

e.g. local user

creationType": "NameCoexistence"

"mailNickname": "91...61"

"userPrincipalName": "91...61@b2cnz.onmicrosoft.com"

e.g. Facebook user

"creationType": null

"otherMails": [
        "Facebook email"
      ]

http://schemas.microsoft.com/identity/claims/identityprovider    facebook.com
     
"userPrincipalName": "cpim_37...a7@b2c.onmicrosoft.com"

These users can sign-in to an application secured by B2C.

A key point is that the local users have an external email e.g. joe.bloggs@hotmail.com whereas the admin. users typically have an email like joe.bloggs@tenant.onmicrosoft.com

Enjoy!

Tuesday, June 14, 2016

Azure B2C : Integrating with Azure "Easy Auth"

I've done a series of posts around integrating applications with Azure AD B2C.

The theme to all of them is that B2C extends OAuth by adding the profiles to the request.

There's an example of this in the sample.

Another solution is to bridge "normal" OAuth and this extension with something like IdentityServer as described here.

And then I came across this article - App Service Auth and Azure AD B2C.

If your application is a web application in Azure (i.e. an app service), you can now integrate with B2C as per the article by using "easy auth".

What this means is that you can add the extended support via a few mouse clicks.

The end result is that your application can now connect directly to B2C without a bridge.

Powerful stuff!

There are a few gotchas as mentioned in the article.

You do not need an Azure subscription to create a B2C directory. However, you do need one to create an app. service that is required to get this to work.

So create another subscription and then map this to the B2C directory.

You can do this in the old Azure portal:


Another gotcha is that when you login to the new Azure portal, you may be in the wrong directory and get all sorts of access denied / rights issues.

You can make sure that you are in the B2C directory by clicking on your login name (top right) and then selecting the B2C directory in the "Directory" section in the drop down.

The third gotcha is to note this sentence "Note that in step 2, you’ll need to use the https address of the web app". If you just use the http address, you get a "URL must be in same domain" error.

Once authenticated, a quick way to see what claims you have is to to look in the trace.

Looking at the token in jwt.io, I see:


Now if you go to the web application and add "/.auth/me" to the URL i.e. something like:

https://xxx.azurewebsites.net/.auth/me

you get the JSON token:

etc.

Footnote:

If you take all the social logins that are possible, you start off in IdentityServer with:

Facebook, Google and Twitter

Working up the chain, Easy auth adds:

MSA, Facebook, Google, and Twitter

B2C adds:

MSA, Facebook, Google, LinkedIn, and Amazon

which could all end up in complete confusion :-)

Enjoy!

ADFS : All good things come to an end

One upon a time way back in 2008, Microsoft came up with a new direction for authentication and authorisation called "Claims-based authentication".

They had a new STS (that became ADFS) that had the codename "Geneva" and a new set of client-side classes to handle the WS-Fed interaction with Geneva called WIF.

It was announced in a blog post on November 3rd 2008.

And Vittorio Bertocci came on board as an evangelist to help spread the word.

To handle all the inevitable teething problems they created a forum. This was mainly focused on development.

The world rolls on, claims are now mainstream and underpin the Microsoft stack e.g. Office 365, Azure AD, SharePoint, CRM Dynamics etc.

WIF rolled through to OWIN (Katana) and OWIN is rolling through to IdentityServer in .NET Core.

ADFS 2.0 will shortly become ADFS 4.0 with far more functionality.

The ADFS proxy became WAP.

Vittorio is now a Principal PM with the Azure AD team.

And so this forum has closed.

Which is sad in a way. Looking back through my history, I first started answering questions in June 2011 - five long years ago.

Since then, I've contributed to almost 700 questions and hopefully helped a lot of people trying to get to grips with these products.

The content is still fully searchable so all that goodness lives on.

The good news is the forum lives on in a more focused way.

Hope to see you there!

Enjoy!

Thursday, June 09, 2016

Azure B2C : FAQ

There is a lot of confusion around Azure Active Directory (AD) B2C as to where it sits so I thought I would do a FAQ around the questions I've been asked.

I will update this as new questions come in or feel free ask away in the comments.

Overview here.

Official Azure AD B2C FAQ here.

Q: How do I add a SaaS application to B2C?

A: B2C only supports Open ID Connect. It needs some OAuth tweaks to add in profile details. If the SaaS application can make those changes, then yes. If not, you need a bridge (see link). To support WS-Fed and SAML 2.0 you need a bridge as described here. (But note "easy auth" link below).

Q: I see that you used IdentityServer as a bridge. Is that the only solution?

A: No - you could use something like Auth0 as well. The key is that it has to be customisable and it has to be able to support both CP and RP.

Q: ADFS v4.0 (Server 2016) supports OIDC. Could I use this as a bridge?

A: No - ADFS v4.0 is not customisable and it only supports OIDC as a RP not as a CP.

Q: How can I do SSO with ADFS and B2C?

A: At the moment you can't. As above there is no way to connect them directly. However, you could try something like:

Application --> WS-Fed / SAML / OIDC --> ADFS --> WS-Fed / SAML --> IdentityServer --> OIDC --> B2C.

Q: Azure B2C runs on Azure AD. I can set up a federated tenant with ADFS and Azure AD. So why can't I do this with B2C?

A: B2C is a "different kind" of Azure AD tenant. It was developed for a use case of millions of external users that have no need for SaaS or federation.

Q: Can I use AAD Connect to provision my users in B2C?

A: No - that only works for "normal" Azure AD. In addition,  AAD Connect provisions users from AD. Typically, these are internal users inside a company's intranet. B2C supports a different use case - external users not directly employed by a company and on the internet. So it wouldn't make sense to use AAD Connect.

Q: So I can't programmatically provision my users in B2C?

A:  Yes you can via the Graph API. Have a look at the sample.

Q: Does B2C allow SSO across applications?

A: All applications that can authenticate with B2C have SSO across them.

Q: What about logout from B2C?

A: That's more a function of OIDC and currently there is no standardised logout functionality.

Q: Can I use the NuGet Microsoft OWIN OIDC package to connect to B2C?

A: No not OOTB - B2C uses profiles and these profiles have to be added to the OAuth message. Refer B2C sample code.

Q: So I can't use any standard OIDC library?

A: Not OOTB - they require customisation.

Q: My application is already hosted in Azure as an app. service. Can I integrate that?

A: Yes - refer to this "easy auth" link.

Q. What about other languages e.g Java?

A: I have heard of people using a Java OIDC library that they customised.

Q: I already have an Azure AD tenant. Can I use that for B2C?

A:  No - B2C is a "different kind" of Azure AD tenant. When you create a new Azure AD tenant, you'll see there is a check-box that asks you if this is for B2C. The Azure AD tenant is either "normal" or B2C - it can't be both.

Q: I have a number of different logons on B2C - local and some social. However, they are all for the same person i.e. me. Is there any way to link all these identities?

A: No - not at the moment.

Q: Can I add other social providers?

A: No - not at the moment.

Enjoy!

Azure B2C : Integration with IdentityServer

This post covered an overview of Azure Active Directory (AD) B2C and described some of the gotchas.

Imagine you have purchased a SaaS application that supports "normal" OpenID Connect. The vendor has quoted a ridiculous price to add the profile support necessary for the SaaS application to connect to Azure B2C.

One way around this (as you guessed from the title!)  is to add IdentityServer into the mix.

The path would then be:

SaaS application --> normal OIDC --> IdentityServer --> add profile info. to OIDC --> Azure B2C

The Azure AD B2C sample is Azure AD B2C preview: Build a .NET web app.

We need to add Azure B2C to IdentityServer as an external OIDC CP.

The SaaS application is added to IdentityServer as an OIDC RP.

For simplicity, just sign-in is covered. I'm assuming the user has already registered themselves.

As usual, here is the gist.

(Note that this is still a work in progress. Some B2C claims are not being passed through. I'm still investigating that. Hopefully, this does provide some guidance).

To test this out, I used this sample as the SaaS application. This uses "normal OIDC" to talk to IdentityServer.

The B2C sign-in profile is configured to allow local account login plus Facebook.

When the user clicks Sign-In in the application. they see this IdentityServer HRD screen.


The user selects "Azure B2C".

They then get redirected to B2C and:


They select "Local Account SignIn" and enter their credentials.

They are then redirected back to the application and see their claims.


To expand this into "SignUp", "Edit Details", "Reset Password" etc. you could have some more buttons on the HRD screen each tied into a different B2C profile.

However, this assumes that all applications will have the same set of authentication providers. For the case where some applications use Facebook only, some use local and Twitter etc. there will have to be some kind of mapping table mapping applications to providers.

And some of you will be asking "What about SaaS applications that use WS-Fed or SAML?". Good question, that was another reason to add IdentityServer into the mix and that is the subject of another post.

Enjoy!

OpenID Connect: Displaying the JWT

Just a quick post as I have had a number of questions around this recently.

If you are tracing an OpenID Connect connection e.g. to ADFS v4.0 or Azure AD, it is often useful to see what is in the JWT.

I use SAML tracer on Firefox. You can use this to trace anything not just SAML!

After authentication, look at the trace.


Here is the HTTP POST to my test application. Note the two tabs.


Now selecting the Parameter tab shows the id_token.

Copy and paste the Base64 string into https:jwt.io .


Paste into this box and you will see the decoded token.

Enjoy!