If you want to secure your Azure ASP.NET app using Azure Active Directory, Visual Studio 2013 does a great job if you create a new one. Here you can find a good article about how to do it.
However, is not so easy and we don’t have too much help if we want to add Azure AD to an existing asp.net app. This post tries to help with that, basically, create a new project configured with Azure AD, and then follow the following steps using the new one as reference:
First you’ll need to add these packages to your project:
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">package</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="EntityFramework"</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="6.1.0"</span> <span style="color: #ff0000">targetFramework</span><span style="color: #0000ff">="net45"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">package</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="Microsoft.AspNet.Identity.Core"</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="2.0.0"</span> <span style="color: #ff0000">targetFramework</span><span style="color: #0000ff">="net45"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">package</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="Microsoft.AspNet.Identity.EntityFramework"</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="2.0.0"</span> <span style="color: #ff0000">targetFramework</span><span style="color: #0000ff">="net45"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">package</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="Microsoft.IdentityModel.Clients.ActiveDirectory"</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="1.0.0"</span> <span style="color: #ff0000">targetFramework</span><span style="color: #0000ff">="net45"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"><</span><span style="color: #800000">package</span> <span style="color: #ff0000">id</span><span style="color: #0000ff">="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry"</span> <span style="color: #ff0000">version</span><span style="color: #0000ff">="4.5.1"</span> <span style="color: #ff0000">targetFramework</span><span style="color: #0000ff">="net45"</span> <span style="color: #0000ff">/></span> |
Copy the Utils folder that contains the class DatabaseIssuerNameRegistry and the Models classes (see image below):
Note: You’ll need an SQL Database for the Authentication stuff. It seems that in recent versions, the identity providers are storing some info about tokens there. In this article from great Vittorio Bertocci there are more information: http://www.cloudidentity.com/blog/2013/10/24/vs2013-rtm-organizational-accounts-and-publishing-to-windows-azure-web-sites/
Copy IdentityConfig.cs to App_Start
Copy AccountController
In the global.asax file:
Copy the method: WSFederationAuthenticationModule_RedirectingToIdentityProvider
In the Application_Start() add:
Copy the Account Views
Copy the Home/UserProfile view
Update the Home controller with the UserProfile action. You will see that you need to add some constants that are defined in the HomeController class
1 |
<span id="lnum1" style="color: #606060"> 1:</span> [Authorize] |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff">public</span> async Task<ActionResult> UserProfile() |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> { |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff">string</span> tenantId = ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value; |
1 |
<span id="lnum5" style="color: #606060"> 5:</span>  |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #008000">// Get a token for calling the Windows Azure Active Directory Graph</span> |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> AuthenticationContext authContext = <span style="color: #0000ff">new</span> AuthenticationContext(String.Format(CultureInfo.InvariantCulture, LoginUrl, tenantId)); |
1 |
<span id="lnum8" style="color: #606060"> 8:</span> ClientCredential credential = <span style="color: #0000ff">new</span> ClientCredential(AppPrincipalId, AppKey); |
1 |
<span id="lnum9" style="color: #606060"> 9:</span> AuthenticationResult assertionCredential = authContext.AcquireToken(GraphUrl, credential); |
1 |
<span id="lnum10" style="color: #606060"> 10:</span> <span style="color: #0000ff">string</span> authHeader = assertionCredential.CreateAuthorizationHeader(); |
1 |
<span id="lnum11" style="color: #606060"> 11:</span> <span style="color: #0000ff">string</span> requestUrl = String.Format( |
1 |
<span id="lnum12" style="color: #606060"> 12:</span> CultureInfo.InvariantCulture, |
1 |
<span id="lnum13" style="color: #606060"> 13:</span> GraphUserUrl, |
1 |
<span id="lnum14" style="color: #606060"> 14:</span> HttpUtility.UrlEncode(tenantId), |
1 |
<span id="lnum15" style="color: #606060"> 15:</span> HttpUtility.UrlEncode(User.Identity.Name)); |
1 |
<span id="lnum16" style="color: #606060"> 16:</span>  |
1 |
<span id="lnum17" style="color: #606060"> 17:</span> HttpClient client = <span style="color: #0000ff">new</span> HttpClient(); |
1 |
<span id="lnum18" style="color: #606060"> 18:</span> HttpRequestMessage request = <span style="color: #0000ff">new</span> HttpRequestMessage(HttpMethod.Get, requestUrl); |
1 |
<span id="lnum19" style="color: #606060"> 19:</span> request.Headers.TryAddWithoutValidation(<span style="color: #006080">"Authorization"</span>, authHeader); |
1 |
<span id="lnum20" style="color: #606060"> 20:</span> HttpResponseMessage response = await client.SendAsync(request); |
1 |
<span id="lnum21" style="color: #606060"> 21:</span> <span style="color: #0000ff">string</span> responseString = await response.Content.ReadAsStringAsync(); |
1 |
<span id="lnum22" style="color: #606060"> 22:</span> UserProfile profile = JsonConvert.DeserializeObject<UserProfile>(responseString); |
1 |
<span id="lnum23" style="color: #606060"> 23:</span>  |
1 |
<span id="lnum24" style="color: #606060"> 24:</span> <span style="color: #0000ff">return</span> View(profile); |
1 |
<span id="lnum25" style="color: #606060"> 25:</span> } |
Copy LoginPartial view
Add this code to _Layout.cshtml file
OK. Now you need to configure some bits in the Azure portal. Basically, what you need to do is adding permissions for your app in the Azure AD.
In Azure Management Portal, go to the Active Directory and Applications, and Add a new Application:
The sign on URL is where your app will go when you navigate to your app without being logged in. Usually will be you same home page (has to be SSL)
The App ID URI has to be your Azure Active Directory URL, followed for some app name or ID. You can see your Azure AD URL managing your Azure AD in the Domains section. If you are in the Azure tenant for Office 365, the AD URL will be the same Office 365 main URL: https://tenant_name.sharepoint.com
Then, in the Configure page, you have to add a Key:
Save the config and you’ll see the Key value:
You also need to copy the Client ID
If you want to allow Read/Write Azure AD data, you need to configure permissions. If you have copy the HomeController as I told you before, the UserProfile action is trying to read the Active Directory, so, you need to give it permissions or you will get an error.
We’re done with the Azure management portal, now, grab the Client ID and Key value, and come back to the asp.net project, let’s update the web.config file with all the Identity providers and config.
In ConfigSections:
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="system.identityModel"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">section</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="system.identityModel.services"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"</span> <span style="color: #0000ff">/></span> |
Add the ConnectionString. Here you can set a local DB value, and later, when you publish to Azure, Visual Studio will detect that you’re using a connection string, and will show you the assistant to connect to the SQL DB in Azure.
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">connectionStrings</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="DefaultConnection"</span> <span style="color: #ff0000">connectionString</span><span style="color: #0000ff">="Data Source=(LocalDb)v11.0;AttachDbFilename=|DataDirectory|aspnet-MyLocalDB-20140522115400.mdf;Initial Catalog=aspnet-MyLocalDB-20140522115400;Integrated Security=True"</span> <span style="color: #ff0000">providerName</span><span style="color: #0000ff">="System.Data.SqlClient"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"></</span><span style="color: #800000">connectionStrings</span><span style="color: #0000ff">></span> |
Note: If you try to connect to Azure SQL DB from Visual Studio, you probably will need to configure the Allowed IP Addresses. You have more info in this article: http://azure.microsoft.com/en-us/documentation/articles/web-sites-dotnet-deploy-aspnet-mvc-app-membership-oauth-sql-database/
Add these AppSettings, review all the values that comes from the config you’ve done in Azure portal:
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">key</span><span style="color: #0000ff">="ida:FederationMetadataLocation"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="https://login.windows.net/YOUR_Azure_AD_URL/FederationMetadata/2007-06/FederationMetadata.xml"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">key</span><span style="color: #0000ff">="ida:Realm"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="APP ID URI created in Azure portal"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">key</span><span style="color: #0000ff">="ida:AudienceUri"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="APP ID URI created in Azure portal"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">key</span><span style="color: #0000ff">="ida:ClientID"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="12431234212342123412341243"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">key</span><span style="color: #0000ff">="ida:Password"</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="AKSHFD8943DRKSH8HKFD49"</span> <span style="color: #0000ff">/></span> |
Add:
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">location</span> <span style="color: #ff0000">path</span><span style="color: #0000ff">="Account"</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">system.web</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">authorization</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">allow</span> <span style="color: #ff0000">users</span><span style="color: #0000ff">="*"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"></</span><span style="color: #800000">authorization</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff"></</span><span style="color: #800000">system.web</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> <span style="color: #0000ff"></</span><span style="color: #800000">location</span><span style="color: #0000ff">></span> |
Adding in System.Web
Add (again, review all the values)
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">system.identityModel</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">identityConfiguration</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">issuerNameRegistry</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="YOUR-PROJECT-NAMESPACE.Utils.DatabaseIssuerNameRegistry, NAMESPACE"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">audienceUris</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">value</span><span style="color: #0000ff">="SAME APP ID URI"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff"></</span><span style="color: #800000">audienceUris</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum7" style="color: #606060"> 7:</span> <span style="color: #0000ff"><</span><span style="color: #800000">securityTokenHandlers</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum8" style="color: #606060"> 8:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum9" style="color: #606060"> 9:</span> <span style="color: #0000ff"><</span><span style="color: #800000">remove</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum10" style="color: #606060"> 10:</span> <span style="color: #0000ff"></</span><span style="color: #800000">securityTokenHandlers</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum11" style="color: #606060"> 11:</span> <span style="color: #0000ff"><</span><span style="color: #800000">certificateValidation</span> <span style="color: #ff0000">certificateValidationMode</span><span style="color: #0000ff">="None"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum12" style="color: #606060"> 12:</span> <span style="color: #0000ff"></</span><span style="color: #800000">identityConfiguration</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum13" style="color: #606060"> 13:</span> <span style="color: #0000ff"></</span><span style="color: #800000">system.identityModel</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">system.webServer</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">modules</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="WSFederationAuthenticationModule"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span> <span style="color: #ff0000">preCondition</span><span style="color: #0000ff">="managedHandler"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">add</span> <span style="color: #ff0000">name</span><span style="color: #0000ff">="SessionAuthenticationModule"</span> <span style="color: #ff0000">type</span><span style="color: #0000ff">="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"</span> <span style="color: #ff0000">preCondition</span><span style="color: #0000ff">="managedHandler"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"></</span><span style="color: #800000">modules</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff"></</span><span style="color: #800000">system.webServer</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum1" style="color: #606060"> 1:</span> <span style="color: #0000ff"><</span><span style="color: #800000">system.identityModel.services</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum2" style="color: #606060"> 2:</span> <span style="color: #0000ff"><</span><span style="color: #800000">federationConfiguration</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum3" style="color: #606060"> 3:</span> <span style="color: #0000ff"><</span><span style="color: #800000">cookieHandler</span> <span style="color: #ff0000">requireSsl</span><span style="color: #0000ff">="true"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum4" style="color: #606060"> 4:</span> <span style="color: #0000ff"><</span><span style="color: #800000">wsFederation</span> <span style="color: #ff0000">passiveRedirectEnabled</span><span style="color: #0000ff">="true"</span> <span style="color: #ff0000">issuer</span><span style="color: #0000ff">="https://login.windows.net/AZURE AD URL/wsfed"</span> <span style="color: #ff0000">realm</span><span style="color: #0000ff">="APP ID URI"</span> <span style="color: #ff0000">requireHttps</span><span style="color: #0000ff">="true"</span> <span style="color: #0000ff">/></span> |
1 |
<span id="lnum5" style="color: #606060"> 5:</span> <span style="color: #0000ff"></</span><span style="color: #800000">federationConfiguration</span><span style="color: #0000ff">></span> |
1 |
<span id="lnum6" style="color: #606060"> 6:</span> <span style="color: #0000ff"></</span><span style="color: #800000">system.identityModel.services</span><span style="color: #0000ff">></span> |
And that’s all !! remember to take care of all the URLs and IDs, but if you publish to Azure, you should get the Azure AD login page.
Extra ball !!
OK. You’ve done that, however, when you go to your home page, you find a redirect to the “old style” Forms authentication Login.aspx page… WTH !!
No panic, you’re not gonna believe the reason, but ensure you don’t have the WebMatrix.Data.dll in your BIN folder… yes! it’s true
I found the solution in this post:
Take care because you can remove the DLL from your project, but if it’s already in your Azure website, I suggest that you browse the BIN folder in the Azure site using Visual Studio Server explorer to ensure the DLL is not there (remove it manually if needed).
Hope it helps!!
Luis Manez
@luismanez
Deja un comentario