From 46f5c107b878ba9489770242a6f840a1ac5cbc71 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 7 Jun 2016 00:20:05 +0200 Subject: [PATCH] commentaire nul --- AuthorizationController.cs | 213 ++++++++++++++++++ Yavsc/src/Auth/GoogleHandler.cs | 1 - Yavsc/src/Controllers/OAuthController.cs | 44 +++- .../Controllers/AuthenticationController.cs | 6 +- testOauthClient/Startup.cs | 23 +- testOauthClient/YavscOAuthHandler.cs | 157 +++++++++++++ testOauthClient/YavscOAuthMiddleware.cs | 80 +++++++ testOauthClient/YavscOAuthOptions.cs | 24 ++ testOauthClient/appsettings.json | 6 + testOauthClient/project.json | 7 +- 10 files changed, 545 insertions(+), 16 deletions(-) create mode 100644 AuthorizationController.cs create mode 100644 testOauthClient/YavscOAuthHandler.cs create mode 100644 testOauthClient/YavscOAuthMiddleware.cs create mode 100644 testOauthClient/YavscOAuthOptions.cs diff --git a/AuthorizationController.cs b/AuthorizationController.cs new file mode 100644 index 00000000..d639653e --- /dev/null +++ b/AuthorizationController.cs @@ -0,0 +1,213 @@ +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using AspNet.Security.OpenIdConnect.Extensions; +using AspNet.Security.OpenIdConnect.Server; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http.Authentication; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Mvc.Server.Models; + +namespace Mvc.Server.Controllers { + public class AuthorizationController : Controller { + private readonly ApplicationContext database; + + public AuthorizationController(ApplicationContext database) { + this.database = database; + } + + [HttpGet("~/connect/authorize"), HttpPost("~/connect/authorize")] + public async Task Authorize(CancellationToken cancellationToken) { + // Note: when a fatal error occurs during the request processing, an OpenID Connect response + // is prematurely forged and added to the ASP.NET context by OpenIdConnectServerHandler. + // You can safely remove this part and let ASOS automatically handle the unrecoverable errors + // by switching ApplicationCanDisplayErrors to false in Startup.cs. + var response = HttpContext.GetOpenIdConnectResponse(); + if (response != null) { + return View("Error", response); + } + + // Extract the authorization request from the ASP.NET environment. + var request = HttpContext.GetOpenIdConnectRequest(); + if (request == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.ServerError, + ErrorDescription = "An internal error has occurred" + }); + } + + // Note: authentication could be theorically enforced at the filter level via AuthorizeAttribute + // but this authorization endpoint accepts both GET and POST requests while the cookie middleware + // only uses 302 responses to redirect the user agent to the login page, making it incompatible with POST. + // To work around this limitation, the OpenID Connect request is automatically saved in the cache and will be + // restored by the OpenID Connect server middleware after the external authentication process has been completed. + if (!User.Identities.Any(identity => identity.IsAuthenticated)) { + return Challenge(new AuthenticationProperties { + RedirectUri = Url.Action(nameof(Authorize), new { + request_id = request.GetRequestId() + }) + }); + } + + // Note: ASOS automatically ensures that an application corresponds to the client_id specified + // in the authorization request by calling IOpenIdConnectServerProvider.ValidateAuthorizationRequest. + // In theory, this null check shouldn't be needed, but a race condition could occur if you + // manually removed the application details from the database after the initial check made by ASOS. + var application = await GetApplicationAsync(request.ClientId, cancellationToken); + if (application == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.InvalidClient, + ErrorDescription = "Details concerning the calling client application cannot be found in the database" + }); + } + + // Note: in a real world application, you'd probably prefer creating a specific view model. + return View("Authorize", Tuple.Create(request, application)); + } + + [Authorize, HttpPost("~/connect/authorize/accept"), ValidateAntiForgeryToken] + public async Task Accept(CancellationToken cancellationToken) { + var response = HttpContext.GetOpenIdConnectResponse(); + if (response != null) { + return View("Error", response); + } + + var request = HttpContext.GetOpenIdConnectRequest(); + if (request == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.ServerError, + ErrorDescription = "An internal error has occurred" + }); + } + + // Create a new ClaimsIdentity containing the claims that + // will be used to create an id_token, a token or a code. + var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); + + // Copy the claims retrieved from the external identity provider + // (e.g Google, Facebook, a WS-Fed provider or another OIDC server). + foreach (var claim in HttpContext.User.Claims) { + // Allow ClaimTypes.Name to be added in the id_token. + // ClaimTypes.NameIdentifier is automatically added, even if its + // destination is not defined or doesn't include "id_token". + // The other claims won't be visible for the client application. + if (claim.Type == ClaimTypes.Name) { + claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, + OpenIdConnectConstants.Destinations.IdentityToken); + } + + identity.AddClaim(claim); + } + + var application = await GetApplicationAsync(request.ClientId, cancellationToken); + if (application == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.InvalidClient, + ErrorDescription = "Details concerning the calling client application cannot be found in the database" + }); + } + + // Create a new ClaimsIdentity containing the claims associated with the application. + // Note: setting identity.Actor is not mandatory but can be useful to access + // the whole delegation chain from the resource server (see ResourceController.cs). + identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); + identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID); + + identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, + OpenIdConnectConstants.Destinations.AccessToken, + OpenIdConnectConstants.Destinations.IdentityToken); + + // Create a new authentication ticket holding the user identity. + var ticket = new AuthenticationTicket( + new ClaimsPrincipal(identity), + new AuthenticationProperties(), + OpenIdConnectServerDefaults.AuthenticationScheme); + + // Set the list of scopes granted to the client application. + // Note: this sample always grants the "openid", "email" and "profile" scopes + // when they are requested by the client application: a real world application + // would probably display a form allowing to select the scopes to grant. + ticket.SetScopes(new[] { + /* openid: */ OpenIdConnectConstants.Scopes.OpenId, + /* email: */ OpenIdConnectConstants.Scopes.Email, + /* profile: */ OpenIdConnectConstants.Scopes.Profile, + /* offline_access: */ OpenIdConnectConstants.Scopes.OfflineAccess + }.Intersect(request.GetScopes())); + + // Set the resources servers the access token should be issued for. + ticket.SetResources("resource_server"); + + // Returning a SignInResult will ask ASOS to serialize the specified identity to build appropriate tokens. + // Note: you should always make sure the identities you return contain ClaimTypes.NameIdentifier claim. + // In this sample, the identity always contains the name identifier returned by the external provider. + return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); + } + + [Authorize, HttpPost("~/connect/authorize/deny"), ValidateAntiForgeryToken] + public IActionResult Deny(CancellationToken cancellationToken) { + var response = HttpContext.GetOpenIdConnectResponse(); + if (response != null) { + return View("Error", response); + } + + var request = HttpContext.GetOpenIdConnectRequest(); + if (request == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.ServerError, + ErrorDescription = "An internal error has occurred" + }); + } + + // Notify ASOS that the authorization grant has been denied by the resource owner. + // Note: OpenIdConnectServerHandler will automatically take care of redirecting + // the user agent to the client application using the appropriate response_mode. + return Forbid(OpenIdConnectServerDefaults.AuthenticationScheme); + } + + [HttpGet("~/connect/logout")] + public async Task Logout(CancellationToken cancellationToken) { + var response = HttpContext.GetOpenIdConnectResponse(); + if (response != null) { + return View("Error", response); + } + + // When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired. + // When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved + // using AuthenticateAsync or using User when the authorization server is declared as AuthenticationMode.Active. + var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme); + + var request = HttpContext.GetOpenIdConnectRequest(); + if (request == null) { + return View("Error", new OpenIdConnectMessage { + Error = OpenIdConnectConstants.Errors.ServerError, + ErrorDescription = "An internal error has occurred" + }); + } + + return View("Logout", Tuple.Create(request, identity)); + } + + [HttpPost("~/connect/logout")] + [ValidateAntiForgeryToken] + public ActionResult Logout() { + // Returning a SignOutResult will ask the cookies middleware to delete the local cookie created when + // the user agent is redirected from the external identity provider after a successful authentication flow + // and will redirect the user agent to the post_logout_redirect_uri specified by the client application. + return SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationScheme); + } + + protected virtual Task GetApplicationAsync(string identifier, CancellationToken cancellationToken) { + // Retrieve the application details corresponding to the requested client_id. + return (from application in database.Applications + where application.ApplicationID == identifier + select application).SingleOrDefaultAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/Yavsc/src/Auth/GoogleHandler.cs b/Yavsc/src/Auth/GoogleHandler.cs index c24c77df..22dbc868 100644 --- a/Yavsc/src/Auth/GoogleHandler.cs +++ b/Yavsc/src/Auth/GoogleHandler.cs @@ -26,7 +26,6 @@ namespace Yavsc.Auth AuthenticationProperties properties, OAuthTokenResponse tokens ) { - // TODO use Options.AuthenticationType instead of Bearer ? // Get the Google user var request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokens.AccessToken); diff --git a/Yavsc/src/Controllers/OAuthController.cs b/Yavsc/src/Controllers/OAuthController.cs index df115106..51dc88f8 100644 --- a/Yavsc/src/Controllers/OAuthController.cs +++ b/Yavsc/src/Controllers/OAuthController.cs @@ -5,6 +5,7 @@ using System.Threading; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Extensions; using AspNet.Security.OpenIdConnect.Server; +using Microsoft.AspNet.Authentication; using Microsoft.AspNet.Authorization; using Microsoft.AspNet.Builder; using Microsoft.AspNet.DataProtection.KeyManagement; @@ -241,6 +242,7 @@ namespace Yavsc.Controllers || claim.Type == ClaimTypes.NameIdentifier ) { claim.WithDestination( "code" ); claim.WithDestination( "id_token" ); + claim.WithDestination( "token" ); } identity.AddClaim(claim); @@ -260,7 +262,7 @@ namespace Yavsc.Controllers // the whole delegation chain from the resource server (see ResourceController.cs). identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme); identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID); - identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, "code id_token"); + identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName); var properties = new AuthenticationProperties(); @@ -278,8 +280,6 @@ namespace Yavsc.Controllers properties.SetResources(new[] { _siteSettings.Audience }); - - // This call will instruct AspNet.Security.OpenIdConnect.Server to serialize // the specified identity to build appropriate tokens (id_token and token). // Note: you should always make sure the identities you return contain either @@ -288,9 +288,43 @@ namespace Yavsc.Controllers // Note: the authenticationScheme parameter must match the value configured in Startup.cs. await HttpContext.Authentication.SignInAsync( "oidc-server", - new ClaimsPrincipal(identity), properties); + new ClaimsPrincipal(identity), properties); + _logger.LogInformation($"request.GrantType: {request.GrantType}"); + _logger.LogInformation($"request.Code: {request.Code}"); + if (request.GrantType == "authorisation_code") { + var reduri=request.BuildRedirectUrl(); + _logger.LogInformation($"{reduri}"); + return Redirect(reduri); + } + if (request.GrantType == "token") { + + } + return new EmptyResult(); + // return new EmptyResult(); + // Create a new authentication ticket holding the user identity. + /*var ticket = new AuthenticationTicket( + new ClaimsPrincipal(identity), + new AuthenticationProperties(), + OpenIdConnectServerDefaults.AuthenticationScheme);*/ + + // Set the list of scopes granted to the client application. + // Note: this sample always grants the "openid", "email" and "profile" scopes + // when they are requested by the client application: a real world application + // would probably display a form allowing to select the scopes to grant. + /* ticket.SetScopes(new[] { + OpenIdConnectConstants.Scopes.OpenId, + OpenIdConnectConstants.Scopes.Email, + OpenIdConnectConstants.Scopes.Profile, + OpenIdConnectConstants.Scopes.OfflineAccess + }.Intersect(request.GetScopes())); */ + + // Set the resources servers the access token should be issued for. + // ticket.SetResources(new string[]{"resource_server"}); + + //var response = HttpContext.GetOpenIdConnectResponse(); + - return new EmptyResult(); + } [HttpPost("~/connect/authorize/deny"), ValidateAntiForgeryToken] diff --git a/testOauthClient/Controllers/AuthenticationController.cs b/testOauthClient/Controllers/AuthenticationController.cs index d9b0119e..51936e3e 100644 --- a/testOauthClient/Controllers/AuthenticationController.cs +++ b/testOauthClient/Controllers/AuthenticationController.cs @@ -1,18 +1,16 @@  -using Microsoft.AspNet.Authentication.OpenIdConnect; using Microsoft.AspNet.Http.Authentication; using Microsoft.AspNet.Mvc; namespace Mvc.Client.Controllers { - public class AuthenticationController : Controller { [HttpGet("~/signin")] public ActionResult SignIn() { // Instruct the OIDC client middleware to redirect the user agent to the identity provider. // Note: the authenticationType parameter must match the value configured in Startup.cs - var properties = new AuthenticationProperties { RedirectUri = "http://localhost:5002/signin-oidc" }; - return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties); + var properties = new AuthenticationProperties { RedirectUri = "http://localhost:5002/signin-yavsc" }; + return new ChallengeResult("yavsc", properties); } } diff --git a/testOauthClient/Startup.cs b/testOauthClient/Startup.cs index dc1ac311..047a3fd4 100755 --- a/testOauthClient/Startup.cs +++ b/testOauthClient/Startup.cs @@ -12,6 +12,8 @@ using Microsoft.AspNet.Authentication; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.AspNet.Http; using Microsoft.AspNet.Authentication.Cookies; +using Yavsc.Auth; +using Microsoft.Extensions.WebEncoders; namespace testOauthClient { @@ -36,6 +38,8 @@ namespace testOauthClient options.SignInScheme = "ClientCookie"; }); + services.AddTransient(); + services.AddAuthentication(); services.AddMvc(); @@ -60,6 +64,20 @@ namespace testOauthClient options.AuthenticationDescriptions.Clear(); }); app.UseStaticFiles(); + app.UseOAuthAuthentication( + options => {  + options.AuthenticationScheme="yavsc"; + options.AuthorizationEndpoint="http://dev.pschneider.fr/signin"; + options.TokenEndpoint="http://dev.pschneider.fr/token"; + options.AutomaticAuthenticate=true; + options.AutomaticChallenge=true; + options.CallbackPath=new PathString("/signin-yavsc"); + options.ClaimsIssuer="http://dev.pschneider.fr"; + options.ClientId="016c5ae4-f4cd-40e3-b250-13701c871ecd"; + options.ClientSecret="blahblah"; + } + ); + app.UseCookieAuthentication(new CookieAuthenticationOptions { AutomaticAuthenticate = true, AutomaticChallenge = true, @@ -70,9 +88,8 @@ namespace testOauthClient LogoutPath = new PathString("/signout") }); - - app.UseOpenIdConnectAuthentication( + /* app.UseOpenIdConnectAuthentication( options => { options.AuthenticationScheme = OpenIdConnectDefaults.AuthenticationScheme; options.RequireHttpsMetadata = false; @@ -97,7 +114,7 @@ namespace testOauthClient options.Scope.Clear(); options.Scope.Add("openid"); // .Add("api-resource-controller"); - }); + }); */ app.UseMvc(routes => diff --git a/testOauthClient/YavscOAuthHandler.cs b/testOauthClient/YavscOAuthHandler.cs new file mode 100644 index 00000000..4d575f07 --- /dev/null +++ b/testOauthClient/YavscOAuthHandler.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNet.Authentication; +using Microsoft.AspNet.Authentication.OAuth; +using Microsoft.AspNet.Http; +using Microsoft.AspNet.Http.Authentication; +using Microsoft.AspNet.Http.Features.Authentication; +using Microsoft.AspNet.WebUtilities; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; + +namespace Yavsc.Auth +{ + internal class YavscOAuthHandler : OAuthHandler + { + private ILogger _logger; + HttpClient _backchannel; + private SharedAuthenticationOptions _sharedOptions; + public YavscOAuthHandler(HttpClient httpClient, SharedAuthenticationOptions sharedOptions, ILogger logger) + : base(httpClient) + { + _backchannel = httpClient; + _logger = logger; + _sharedOptions = sharedOptions; + } + // TODO: Abstract this properties override pattern into the base class? + protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri) + { + var scope = FormatScope(); + var queryStrings = new Dictionary(StringComparer.OrdinalIgnoreCase); + queryStrings.Add("response_type", "code"); + queryStrings.Add("client_id", Options.ClientId); + queryStrings.Add("redirect_uri", redirectUri); + + AddQueryString(queryStrings, properties, "scope", scope); + + AddQueryString(queryStrings, properties, "access_type", Options.AccessType ); + AddQueryString(queryStrings, properties, "approval_prompt"); + AddQueryString(queryStrings, properties, "login_hint"); + + var state = Options.StateDataFormat.Protect(properties); + queryStrings.Add("state", state); + + var authorizationEndpoint = QueryHelpers.AddQueryString(Options.AuthorizationEndpoint, queryStrings); + return authorizationEndpoint; + } + + private static void AddQueryString(IDictionary queryStrings, AuthenticationProperties properties, + string name, string defaultValue = null) + { + string value; + if (!properties.Items.TryGetValue(name, out value)) + { + value = defaultValue; + } + else + { + // Remove the parameter from AuthenticationProperties so it won't be serialized to state parameter + properties.Items.Remove(name); + } + queryStrings[name] = value; + } + protected new async Task AuthenticateAsync(AuthenticateContext context) + { + AuthenticationProperties properties = null; + + try + { + // ASP.Net Identity requires the NameIdentitifer field to be set or it won't + // accept the external login (AuthenticationManagerExtensions.GetExternalLoginInfo) + + string code = null; + string state = null; + + IReadableStringCollection query = Request.Query; + IList values = query["code"]; + if (values != null && values.Count == 1) + { + code = values[0]; + } + values = query["state"]; + if (values != null && values.Count == 1) + { + state = values[0]; + } + + properties = Options.StateDataFormat.Unprotect(state); + if (properties == null) + { + return null; + } + + // OAuth2 10.12 CSRF + if (!ValidateCorrelationId(properties)) + { + return new AuthenticationTicket(null, properties, this.Options.AuthenticationScheme); + } + + string requestPrefix = Request.Scheme + "://" + Request.Host; + string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath; + + // Build up the body for the token request + var body = new List>(); + body.Add(new KeyValuePair("grant_type", "authorization_code")); + body.Add(new KeyValuePair("code", code)); + body.Add(new KeyValuePair("redirect_uri", redirectUri)); + body.Add(new KeyValuePair("client_id", Options.ClientId)); + body.Add(new KeyValuePair("client_secret", Options.ClientSecret)); + + // Request the token + HttpResponseMessage tokenResponse = + await _backchannel.PostAsync(Options.TokenEndpoint, new FormUrlEncodedContent(body)); + tokenResponse.EnsureSuccessStatusCode(); + string text = await tokenResponse.Content.ReadAsStringAsync(); + + // Deserializes the token response + JObject response = JObject.Parse(text); + string accessToken = response.Value("access_token"); + + if (string.IsNullOrWhiteSpace(accessToken)) + { + _logger.LogWarning("Access token was not found"); + return new AuthenticationTicket(null, properties, this.Options.AuthenticationScheme); + } + + // Get the user + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Options.UserInformationEndpoint); + request.Headers.Authorization = new AuthenticationHeaderValue(this.Options.AuthenticationScheme, accessToken); + HttpResponseMessage graphResponse = await _backchannel.SendAsync(request); + graphResponse.EnsureSuccessStatusCode(); + text = await graphResponse.Content.ReadAsStringAsync(); + JObject user = JObject.Parse(text); + // Read user data + + var id = new ClaimsIdentity( + _sharedOptions.SignInScheme, + ClaimsIdentity.DefaultNameClaimType, + ClaimsIdentity.DefaultRoleClaimType); + context.Authenticated(new ClaimsPrincipal(id) + , new Dictionary(), new Dictionary{ + { "John" , (object) "Doe" } + }); + return new AuthenticationTicket(context.Principal, properties, _sharedOptions.SignInScheme); + } + catch (Exception ex) + { + _logger.LogError("Authentication failed", ex); + return new AuthenticationTicket(null, properties, this.Options.AuthenticationScheme); + } + + } + } +} diff --git a/testOauthClient/YavscOAuthMiddleware.cs b/testOauthClient/YavscOAuthMiddleware.cs new file mode 100644 index 00000000..7776998c --- /dev/null +++ b/testOauthClient/YavscOAuthMiddleware.cs @@ -0,0 +1,80 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNet.Authentication; +using Microsoft.AspNet.Authentication.OAuth; +using Microsoft.AspNet.Builder; +using Microsoft.AspNet.DataProtection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.OptionsModel; +using Microsoft.Extensions.WebEncoders; +namespace Yavsc.Auth +{ + /// + /// An ASP.NET Core middleware for authenticating users using Google OAuth 2.0. + /// + public class YavscOAuthMiddleware : OAuthMiddleware + { + private RequestDelegate _next; + private ILogger _logger; + private SharedAuthenticationOptions _sharedOptions; + + /// + /// Initializes a new . + /// + /// The next middleware in the HTTP pipeline to invoke. + /// + /// + /// + /// + /// Configuration options for the middleware. + public YavscOAuthMiddleware( + RequestDelegate next, + IDataProtectionProvider dataProtectionProvider, + ILoggerFactory loggerFactory, + UrlEncoder encoder, + IOptions sharedOptions, + YavscOAuthOptions options) + : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) + { + if (next == null) + { + throw new ArgumentNullException(nameof(next)); + } + _next = next; + + if (dataProtectionProvider == null) + { + throw new ArgumentNullException(nameof(dataProtectionProvider)); + } + + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _logger = loggerFactory.CreateLogger(); + + if (encoder == null) + { + throw new ArgumentNullException(nameof(encoder)); + } + + if (sharedOptions == null) + { + throw new ArgumentNullException(nameof(sharedOptions)); + } + _sharedOptions = sharedOptions.Value; + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + } + + protected override AuthenticationHandler CreateHandler() + { + return new YavscOAuthHandler(Backchannel,_sharedOptions,_logger); + } + } +} diff --git a/testOauthClient/YavscOAuthOptions.cs b/testOauthClient/YavscOAuthOptions.cs new file mode 100644 index 00000000..6290db6a --- /dev/null +++ b/testOauthClient/YavscOAuthOptions.cs @@ -0,0 +1,24 @@ + + +using Microsoft.AspNet.Authentication.OAuth; +using Microsoft.AspNet.Http; + +public class YavscOAuthOptions : OAuthOptions { + public YavscOAuthOptions() + { + AuthenticationScheme = "yavsc"; + DisplayName = AuthenticationScheme; + CallbackPath = new PathString("/signin-yavsc"); + AuthorizationEndpoint = "http://dev.pschneider.fr/connect/authorize"; + TokenEndpoint = "http://dev.pschneider.fr/api/token/get"; + UserInformationEndpoint = "http://dev.pschneider.fr/api/userinfo"; + Scope.Add("openid"); + Scope.Add("profile"); + Scope.Add("email"); + } + + /// + /// access_type. Set to 'offline' to request a refresh token. + /// + public string AccessType { get; set; } +} \ No newline at end of file diff --git a/testOauthClient/appsettings.json b/testOauthClient/appsettings.json index e5472e56..d16e5fc5 100755 --- a/testOauthClient/appsettings.json +++ b/testOauthClient/appsettings.json @@ -6,5 +6,11 @@ "System": "Information", "Microsoft": "Information" } + }, + "Authentication": {  + "Yavsc": { + "ClientId": "016c5ae4-f4cd-40e3-b250-13701c871ecd", + "ClientSecret": "blahblah" + } } } diff --git a/testOauthClient/project.json b/testOauthClient/project.json index 9bb50d86..bcacb953 100755 --- a/testOauthClient/project.json +++ b/testOauthClient/project.json @@ -7,6 +7,9 @@ "defaultNamespace": "testOauthClient" }, "dependencies": { + "Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-rc1-final", + "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final", + "Microsoft.AspNet.Authentication.OAuth": "1.0.0-rc1-final", "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final", "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", @@ -18,9 +21,7 @@ "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final", "Microsoft.Extensions.Logging": "1.0.0-rc1-final", "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final", - "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final", - "Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-rc1-final", - "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final" + "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final" }, "commands": { "web": "Microsoft.AspNet.Server.Kestrel --server.urls=http://*:5002"