diff --git a/samples/SocialSample/Properties/launchSettings.json b/samples/SocialSample/Properties/launchSettings.json
index 15c91efdcb..e9d26ad03e 100644
--- a/samples/SocialSample/Properties/launchSettings.json
+++ b/samples/SocialSample/Properties/launchSettings.json
@@ -4,13 +4,14 @@
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:54540",
- "sslPort": 0
+ "sslPort": 44318
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
+ "launchUrl": "https://localhost:44318/",
"environmentVariables": {
"ASPNET_ENV": "Development"
}
@@ -18,10 +19,9 @@
"web": {
"commandName": "web",
"launchBrowser": true,
- "launchUrl": "http://localhost:54540/",
+ "launchUrl": "https://localhost:54541/",
"environmentVariables": {
- "Hosting:Environment": "Development",
- "ASPNET_server.urls": "http://localhost:54540/"
+ "Hosting:Environment": "Development"
}
}
}
diff --git a/samples/SocialSample/Startup.cs b/samples/SocialSample/Startup.cs
index 108ad6ff86..358a031cd3 100644
--- a/samples/SocialSample/Startup.cs
+++ b/samples/SocialSample/Startup.cs
@@ -1,8 +1,11 @@
using System;
+using System.IO;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
+using System.Reflection;
using System.Security.Claims;
+using System.Security.Cryptography.X509Certificates;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
@@ -15,12 +18,15 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
+using Microsoft.AspNetCore.HttpOverrides;
+using Microsoft.AspNetCore.Server.Kestrel.Filter;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
-namespace CookieSample
+namespace SocialSample
{
/* Note all servers must use the same address and port because these are pre-registered with the various providers. */
public class Startup
@@ -45,6 +51,10 @@ namespace CookieSample
{
loggerfactory.AddConsole(LogLevel.Information);
+ //Configure SSL
+ var serverCertificate = LoadCertificate();
+ app.UseKestrelHttps(serverCertificate);
+
// Simple error page to avoid a repo dependency.
app.Use(async (context, next) =>
{
@@ -63,6 +73,12 @@ namespace CookieSample
}
});
+ // Forward the scheme from IISPlatformHandler
+ app.UseForwardedHeaders(new ForwardedHeadersOptions()
+ {
+ ForwardedHeaders = ForwardedHeaders.XForwardedProto,
+ });
+
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AutomaticAuthenticate = true,
@@ -105,7 +121,6 @@ namespace CookieSample
Events = new OAuthEvents()
{
OnRemoteFailure = ctx =>
-
{
ctx.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(ctx.Failure.Message));
ctx.HandleResponse();
@@ -132,45 +147,34 @@ namespace CookieSample
}
});
- // You must first create an app with live.com and add it's ID and Secret to your config.json or user-secrets.
- /* https://account.live.com/developers/applications
- The MicrosoftAccount service has restrictions that prevent the use of http://localhost:54540/ for test applications.
- As such, here is how to change this sample to uses http://mssecsample.localhost.this:54540/ instead.
-
- Edit the hosting.json file and add "server.urls": "http://mssecsample.localhost.this:54540/".
-
- From an admin command console first enter:
- notepad C:\Windows\System32\drivers\etc\hosts
- and add this to the file, save, and exit (and reboot?):
- 127.0.0.1 MsSecSample.localhost.this
-
- [WebListener] Then you can choose to run the app as admin (see below) or add the following ACL as admin:
- netsh http add urlacl url=http://mssecsample.localhost.this:54540/ user=[domain\user]
-
- The sample app can then be run via:
- dnx web
+ /* Azure AD app model v2 has restrictions that prevent the use of plain HTTP for redirect URLs.
+ Therefore, to authenticate through microsoft accounts, tryout the sample using the following URL:
+ https://localhost:54541/
*/
- //app.UseOAuthAuthentication(new OAuthOptions
- //{
- // AuthenticationScheme = "Microsoft-AccessToken",
- // DisplayName = "MicrosoftAccount-AccessToken - Requires project changes",
- // ClientId = Configuration["msa:clientid"],
- // ClientSecret = Configuration["msa:clientsecret"],
- // CallbackPath = new PathString("/signin-microsoft-token"),
- // AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint,
- // TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint,
- // Scope = { "wl.basic" },
- // SaveTokens = true
- //});
+ // See config.json
+ // https://apps.dev.microsoft.com/
+ app.UseOAuthAuthentication(new OAuthOptions
+ {
+ AuthenticationScheme = "Microsoft-AccessToken",
+ DisplayName = "MicrosoftAccount-AccessToken",
+ ClientId = Configuration["msa:clientid"],
+ ClientSecret = Configuration["msa:clientsecret"],
+ CallbackPath = new PathString("/signin-microsoft-token"),
+ AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint,
+ TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint,
+ Scope = { "https://graph.microsoft.com/user.read" },
+ SaveTokens = true
+ });
- ////// You must first create an app with live.com and add it's ID and Secret to your config.json or user-secrets.
- //app.UseMicrosoftAccountAuthentication(new MicrosoftAccountOptions
- //{
- // DisplayName = "MicrosoftAccount - Requires project changes",
- // ClientId = Configuration["msa:clientid"],
- // ClientSecret = Configuration["msa:clientsecret"],
- // Scope = { "wl.emails" }
- //});
+ // See config.json
+ // https://azure.microsoft.com/en-us/documentation/articles/active-directory-v2-app-registration/
+ app.UseMicrosoftAccountAuthentication(new MicrosoftAccountOptions
+ {
+ DisplayName = "MicrosoftAccount",
+ ClientId = Configuration["msa:clientid"],
+ ClientSecret = Configuration["msa:clientsecret"],
+ SaveTokens = true
+ });
// See config.json
// https://github.com/settings/applications/
@@ -346,5 +350,23 @@ namespace CookieSample
host.Run();
}
+
+ private X509Certificate2 LoadCertificate()
+ {
+ var socialSampleAssembly = GetType().GetTypeInfo().Assembly;
+ var embeddedFileProvider = new EmbeddedFileProvider(socialSampleAssembly, "SocialSample");
+ var certificateFileInfo = embeddedFileProvider.GetFileInfo("compiler/resources/cert.pfx");
+ using (var certificateStream = certificateFileInfo.CreateReadStream())
+ {
+ byte[] certificatePayload;
+ using (var memoryStream = new MemoryStream())
+ {
+ certificateStream.CopyTo(memoryStream);
+ certificatePayload = memoryStream.ToArray();
+ }
+
+ return new X509Certificate2(certificatePayload, "testPassword");
+ }
+ }
}
}
diff --git a/samples/SocialSample/compiler/resources/cert.pfx b/samples/SocialSample/compiler/resources/cert.pfx
new file mode 100644
index 0000000000..7118908c2d
Binary files /dev/null and b/samples/SocialSample/compiler/resources/cert.pfx differ
diff --git a/samples/SocialSample/config.json b/samples/SocialSample/config.json
index 13d3ff94a0..5c1453e39f 100644
--- a/samples/SocialSample/config.json
+++ b/samples/SocialSample/config.json
@@ -6,5 +6,7 @@
"github:clientid": "49e302895d8b09ea5656",
"github:clientsecret": "98f1bf028608901e9df91d64ee61536fe562064b",
"github-token:clientid": "8c0c5a572abe8fe89588",
- "github-token:clientsecret": "e1d95eaf03461d27acd6f49d4fc7bf19d6ac8cda"
+ "github-token:clientsecret": "e1d95eaf03461d27acd6f49d4fc7bf19d6ac8cda",
+ "msa:clientid": "e2105565-1f56-434a-ae61-9849ebaf606c",
+ "msa:clientsecret": "pjqtt3RXrFwcfSJyQ0BeUez"
}
diff --git a/samples/SocialSample/project.json b/samples/SocialSample/project.json
index a4c71e0b70..1d02230294 100644
--- a/samples/SocialSample/project.json
+++ b/samples/SocialSample/project.json
@@ -6,9 +6,12 @@
"Microsoft.AspNetCore.Authentication.MicrosoftAccount": "1.0.0-*",
"Microsoft.AspNetCore.Authentication.Twitter": "1.0.0-*",
"Microsoft.AspNetCore.DataProtection": "1.0.0-*",
+ "Microsoft.AspNetCore.HttpOverrides": "1.0.0-*",
"Microsoft.AspNetCore.IISPlatformHandler": "1.0.0-*",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*",
+ "Microsoft.AspNetCore.Server.Kestrel.Https": "1.0.0-*",
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-*",
+ "Microsoft.Extensions.FileProviders.Embedded": "1.0.0-*",
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
"Microsoft.NETCore.Platforms": "1.0.1-*"
},
@@ -26,5 +29,9 @@
]
}
},
- "userSecretsId": "aspnet5-SocialSample-20151210111056"
-}
\ No newline at end of file
+ "userSecretsId": "aspnet5-SocialSample-20151210111056",
+ "content": [
+ "config.json",
+ "project.json"
+ ]
+}
diff --git a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountDefaults.cs b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountDefaults.cs
index d853794779..0d272f9792 100644
--- a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountDefaults.cs
+++ b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountDefaults.cs
@@ -7,10 +7,10 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
public const string AuthenticationScheme = "Microsoft";
- public static readonly string AuthorizationEndpoint = "https://login.live.com/oauth20_authorize.srf";
+ public static readonly string AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
- public static readonly string TokenEndpoint = "https://login.live.com/oauth20_token.srf";
+ public static readonly string TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
- public static readonly string UserInformationEndpoint = "https://apis.live.net/v5.0/me";
+ public static readonly string UserInformationEndpoint = "https://graph.microsoft.com/v1.0/me";
}
}
diff --git a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHandler.cs b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHandler.cs
index 245fbed87d..8b9177625c 100644
--- a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHandler.cs
+++ b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHandler.cs
@@ -38,13 +38,27 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
identity.AddClaim(new Claim("urn:microsoftaccount:id", identifier, ClaimValueTypes.String, Options.ClaimsIssuer));
}
- var name = MicrosoftAccountHelper.GetName(payload);
+ var name = MicrosoftAccountHelper.GetDisplayName(payload);
if (!string.IsNullOrEmpty(name))
{
identity.AddClaim(new Claim(ClaimTypes.Name, name, ClaimValueTypes.String, Options.ClaimsIssuer));
identity.AddClaim(new Claim("urn:microsoftaccount:name", name, ClaimValueTypes.String, Options.ClaimsIssuer));
}
+ var givenName = MicrosoftAccountHelper.GetGivenName(payload);
+ if (!string.IsNullOrEmpty(givenName))
+ {
+ identity.AddClaim(new Claim(ClaimTypes.GivenName, givenName, ClaimValueTypes.String, Options.ClaimsIssuer));
+ identity.AddClaim(new Claim("urn:microsoftaccount:givenname", givenName, ClaimValueTypes.String, Options.ClaimsIssuer));
+ }
+
+ var surname = MicrosoftAccountHelper.GetSurname(payload);
+ if (!string.IsNullOrEmpty(surname))
+ {
+ identity.AddClaim(new Claim(ClaimTypes.Surname, surname, ClaimValueTypes.String, Options.ClaimsIssuer));
+ identity.AddClaim(new Claim("urn:microsoftaccount:surname", surname, ClaimValueTypes.String, Options.ClaimsIssuer));
+ }
+
var email = MicrosoftAccountHelper.GetEmail(payload);
if (!string.IsNullOrEmpty(email))
{
diff --git a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHelper.cs b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHelper.cs
index 8b88cbc44c..cce8dcc73b 100644
--- a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHelper.cs
+++ b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountHelper.cs
@@ -8,7 +8,8 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
{
///
/// Contains static methods that allow to extract user's information from a
- /// instance retrieved from Google after a successful authentication process.
+ /// instance retrieved from Microsoft after a successful authentication process.
+ /// http://graph.microsoft.io/en-us/docs/api-reference/v1.0/resources/user
///
public static class MicrosoftAccountHelper
{
@@ -28,40 +29,40 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
///
/// Gets the user's name.
///
- public static string GetName(JObject user)
+ public static string GetDisplayName(JObject user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
- return user.Value("name");
+ return user.Value("displayName");
}
///
- /// Gets the user's first name.
+ /// Gets the user's given name.
///
- public static string GetFirstName(JObject user)
+ public static string GetGivenName(JObject user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
- return user.Value("first_name");
+ return user.Value("givenName");
}
///
- /// Gets the user's last name.
+ /// Gets the user's surname.
///
- public static string GetLastName(JObject user)
+ public static string GetSurname(JObject user)
{
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
- return user.Value("last_name");
+ return user.Value("surname");
}
///
@@ -74,7 +75,7 @@ namespace Microsoft.AspNetCore.Authentication.MicrosoftAccount
throw new ArgumentNullException(nameof(user));
}
- return user.Value("emails")?.Value("preferred");
+ return user.Value("mail") ?? user.Value("userPrincipalName");
}
}
}
diff --git a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountOptions.cs b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountOptions.cs
index 2783bcef1f..625d4baf9c 100644
--- a/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountOptions.cs
+++ b/src/Microsoft.AspNetCore.Authentication.MicrosoftAccount/MicrosoftAccountOptions.cs
@@ -22,7 +22,7 @@ namespace Microsoft.AspNetCore.Builder
AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint;
TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint;
UserInformationEndpoint = MicrosoftAccountDefaults.UserInformationEndpoint;
- Scope.Add("wl.basic");
+ Scope.Add("https://graph.microsoft.com/user.read");
}
}
}
diff --git a/test/Microsoft.AspNetCore.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs b/test/Microsoft.AspNetCore.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs
index f5a43b8ed2..0ddfb5a3c7 100644
--- a/test/Microsoft.AspNetCore.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs
+++ b/test/Microsoft.AspNetCore.Authentication.Test/MicrosoftAccount/MicrosoftAccountMiddlewareTests.cs
@@ -92,7 +92,7 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
var transaction = await server.SendAsync("http://example.com/challenge");
Assert.Equal(HttpStatusCode.Redirect, transaction.Response.StatusCode);
var location = transaction.Response.Headers.Location.AbsoluteUri;
- Assert.Contains("https://login.live.com/oauth20_authorize.srf", location);
+ Assert.Contains("https://login.microsoftonline.com/common/oauth2/v2.0/authorize", location);
Assert.Contains("response_type=code", location);
Assert.Contains("client_id=", location);
Assert.Contains("redirect_uri=", location);
@@ -113,7 +113,7 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
{
Sender = req =>
{
- if (req.RequestUri.AbsoluteUri == "https://login.live.com/oauth20_token.srf")
+ if (req.RequestUri.AbsoluteUri == "https://login.microsoftonline.com/common/oauth2/v2.0/token")
{
return ReturnJsonResponse(new
{
@@ -123,18 +123,15 @@ namespace Microsoft.AspNetCore.Authentication.Tests.MicrosoftAccount
refresh_token = "Test Refresh Token"
});
}
- else if (req.RequestUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped) == "https://apis.live.net/v5.0/me")
+ else if (req.RequestUri.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped) == "https://graph.microsoft.com/v1.0/me")
{
return ReturnJsonResponse(new
{
id = "Test User ID",
- name = "Test Name",
- first_name = "Test Given Name",
- last_name = "Test Family Name",
- emails = new
- {
- preferred = "Test email"
- }
+ displayName = "Test Name",
+ givenName = "Test Given Name",
+ surname = "Test Family Name",
+ mail = "Test email"
});
}