OAuth Api call success
This commit is contained in:
@ -7,6 +7,7 @@ using Microsoft.AspNet.Mvc;
|
||||
using Yavsc.ViewModels.Account;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Yavsc.Models.Auth;
|
||||
|
||||
namespace Yavsc.WebApi.Controllers
|
||||
{
|
||||
@ -121,18 +122,14 @@ namespace Yavsc.WebApi.Controllers
|
||||
[HttpGet("~/api/me"),Produces("application/json")]
|
||||
public async Task<IActionResult> Me ()
|
||||
{
|
||||
|
||||
if (User==null) return new BadRequestObjectResult(
|
||||
new {
|
||||
error = "no user"
|
||||
});
|
||||
if (User==null)
|
||||
return new BadRequestObjectResult(
|
||||
new { error = "user not found" });
|
||||
var uid = User.GetUserId();
|
||||
if (uid == null)
|
||||
return new BadRequestObjectResult(
|
||||
new {
|
||||
error = "not identified"
|
||||
});
|
||||
return Ok(await UserManager.FindByIdAsync(uid));
|
||||
new { error = "user not identified" });
|
||||
return Ok(new Me(await UserManager.FindByIdAsync(uid)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,147 +0,0 @@
|
||||
//
|
||||
// YavscAuthenticationHandler.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paul@pschneider.fr>
|
||||
//
|
||||
// Copyright (c) 2016 GNU GPL
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yavsc.Authentication
|
||||
{
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
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.Extensions.Logging;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
public static class YavscAuthenticationExtensions
|
||||
{
|
||||
}
|
||||
|
||||
class YavscAuthenticationHandler : OAuthHandler<YavscAuthenticationOptions>
|
||||
{
|
||||
private ILogger _logger;
|
||||
private HttpClient _backchannel;
|
||||
|
||||
public YavscAuthenticationHandler(HttpClient backchannel, ILogger logger) : base (backchannel)
|
||||
{
|
||||
_backchannel = backchannel;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected new async Task<AuthenticationTicket> 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<string> 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<KeyValuePair<string, string>>();
|
||||
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
|
||||
body.Add(new KeyValuePair<string, string>("code", code));
|
||||
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
|
||||
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
|
||||
body.Add(new KeyValuePair<string, string>("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<string>("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(
|
||||
Options.SignInAsAuthenticationType,
|
||||
ClaimsIdentity.DefaultNameClaimType,
|
||||
ClaimsIdentity.DefaultRoleClaimType);
|
||||
context.Authenticated(new ClaimsPrincipal(id)
|
||||
, new Dictionary<string,string>(), new Dictionary<string,object>{
|
||||
{ "John" , (object) "Doe" }
|
||||
});
|
||||
return new AuthenticationTicket(context.Principal, properties, Options.SignInAsAuthenticationType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Authentication failed", ex);
|
||||
return new AuthenticationTicket(null, properties, this.Options.AuthenticationScheme);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,102 +0,0 @@
|
||||
//
|
||||
// YavscAuthenticationMiddleware.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paul@pschneider.fr>
|
||||
//
|
||||
// Copyright (c) 2016 GNU GPL
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
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.Authentication
|
||||
{
|
||||
public class YavscAuthenticationMiddleware : OAuthMiddleware<YavscAuthenticationOptions>
|
||||
{
|
||||
RequestDelegate _next;
|
||||
ILogger _logger;
|
||||
|
||||
public YavscAuthenticationMiddleware(
|
||||
RequestDelegate next,
|
||||
IDataProtectionProvider dataProtectionProvider,
|
||||
ILoggerFactory loggerFactory,
|
||||
UrlEncoder encoder,
|
||||
IOptions<SharedAuthenticationOptions> sharedOptions,
|
||||
YavscAuthenticationOptions 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<YavscAuthenticationMiddleware>();
|
||||
|
||||
if (encoder == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(encoder));
|
||||
}
|
||||
|
||||
if (sharedOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(sharedOptions));
|
||||
}
|
||||
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
if(string.IsNullOrEmpty(options.SignInAsAuthenticationType))
|
||||
{
|
||||
options.SignInAsAuthenticationType = sharedOptions.Value.SignInScheme;
|
||||
}
|
||||
|
||||
if(options.StateDataFormat == null)
|
||||
{
|
||||
var dataProtector = dataProtectionProvider.CreateProtector(typeof(YavscAuthenticationMiddleware).FullName,
|
||||
options.AuthenticationScheme);
|
||||
|
||||
options.StateDataFormat = new PropertiesDataFormat(dataProtector);
|
||||
}
|
||||
}
|
||||
|
||||
// Called for each request, to create a handler for each request.
|
||||
protected override AuthenticationHandler<YavscAuthenticationOptions> CreateHandler()
|
||||
{
|
||||
return new YavscAuthenticationHandler(this.Backchannel,_logger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
//
|
||||
// YavscAuthenticationMiddlewareOptions.cs
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paul@pschneider.fr>
|
||||
//
|
||||
// Copyright (c) 2016 GNU GPL
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
using Microsoft.AspNet.Authentication.OAuth;
|
||||
using Microsoft.AspNet.Http;
|
||||
|
||||
namespace Yavsc.Authentication
|
||||
{
|
||||
|
||||
public class YavscAuthenticationOptions: OAuthOptions
|
||||
{
|
||||
public YavscAuthenticationOptions()
|
||||
{}
|
||||
|
||||
public YavscAuthenticationOptions(string authType, string clientId, string clientSecret)
|
||||
{
|
||||
if (authType == null)
|
||||
throw new NotSupportedException();
|
||||
Description.AuthenticationScheme = authType;
|
||||
ClientId = clientId;
|
||||
ClientSecret = clientSecret;
|
||||
SignInAsAuthenticationType = authType;
|
||||
Scope.Clear();
|
||||
}
|
||||
public PathString TokenPath { get; set; }
|
||||
public PathString AuthorizePath { get; set; }
|
||||
|
||||
public PathString ReturnUrl { get; set; }
|
||||
public PathString LoginPath { get; set; }
|
||||
public PathString LogoutPath { get; set; }
|
||||
|
||||
internal string AuthenticationServerUri = "https://accounts.google.com/o/oauth2/auth";
|
||||
internal string TokenServerUri = "https://accounts.google.com/o/oauth2/token";
|
||||
|
||||
private string signInAsAuthenticationType = null;
|
||||
public string SignInAsAuthenticationType { get
|
||||
{ return signInAsAuthenticationType ; }
|
||||
set { signInAsAuthenticationType = value;
|
||||
ReturnUrl = new PathString("/signin-"+signInAsAuthenticationType.ToLower());
|
||||
} }
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,26 @@ namespace Yavsc
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public const string AccessDeniedPath = "~/signin", AuthorizePath = "~/authorize",
|
||||
TokenPath = "~/token", LocalLoginPath = "~/signin", LoginPath = "~/signin",
|
||||
ExternalLoginPath = "~/extsign", LogoutPath = "~/signout", MePath = "~/api/Me";
|
||||
|
||||
public const string
|
||||
public const string ApplicationName = "Yavsc",
|
||||
CompanyClaimType = "https://schemas.pschneider.fr/identity/claims/Company",
|
||||
UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9 ]*$",
|
||||
AuthorizePath = "~/authorize",
|
||||
TokenPath = "~/token", LoginPath = "~/signin",
|
||||
LogoutPath = "~/signout", UserInfoPath = "~/api/me",
|
||||
ApplicationAuthenticationSheme = "ServerCookie",
|
||||
ExternalAuthenticationSheme= "ExternalCookie";
|
||||
|
||||
ExternalAuthenticationSheme= "ExternalCookie",
|
||||
CompanyInfoUrl = " https://societeinfo.com/app/rest/api/v1/company/json?registration_number={0}&key={1}",
|
||||
DefaultFactor = "Default",
|
||||
MobileAppFactor = "Mobile Application",
|
||||
EMailFactor = "Email",
|
||||
SMSFactor = "SMS",
|
||||
AdminGroupName = "Administrator",
|
||||
BlogModeratorGroupName = "Moderator",
|
||||
FrontOfficeGroupName = "FrontOffice",
|
||||
UserBillsFilesDir= "Bills",
|
||||
UserFilesDir = "UserFiles",
|
||||
GCMNotificationUrl = "https://gcm-http.googleapis.com/gcm/send",
|
||||
KeyProtectorPurpose = "OAuth.AspNet.AuthServer";
|
||||
public static readonly Scope[] SiteScopes = {
|
||||
new Scope { Id = "profile", Description = "Your profile informations" },
|
||||
new Scope { Id = "book" , Description ="Your booking interface"},
|
||||
@ -23,26 +35,9 @@ namespace Yavsc
|
||||
new Scope { Id = "frontoffice" , Description ="Your front office interface" }
|
||||
};
|
||||
|
||||
public const string
|
||||
CompanyInfoUrl = " https://societeinfo.com/app/rest/api/v1/company/json?registration_number={0}&key={1}",
|
||||
DefaultFactor = "Default",
|
||||
MobileAppFactor = "Google.clood",
|
||||
EMailFactor = "Email",
|
||||
SMSFactor = "Phone",
|
||||
AdminGroupName = "Administrator",
|
||||
BlogModeratorGroupName = "Moderator",
|
||||
FrontOfficeGroupName = "FrontOffice",
|
||||
UserBillsFilesDir= "Bills",
|
||||
UserFilesDir = "UserFiles",
|
||||
GCMNotificationUrl = "https://gcm-http.googleapis.com/gcm/send",
|
||||
KeyProtectorPurpose = "OAuth.AspNet.AuthServer";
|
||||
|
||||
private static readonly string[] GoogleScopes = { "openid", "profile", "email" };
|
||||
|
||||
public static readonly string[] GoogleCalendarScopes =
|
||||
{ "openid", "profile", "email", "https://www.googleapis.com/auth/calendar" };
|
||||
public const string ApplicationName = "Yavsc",
|
||||
Issuer = "https://dev.pschneider.fr",
|
||||
CompanyClaimType = "https://schemas.pschneider.fr/identity/claims/Company",
|
||||
UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9 ]*$";
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ using Yavsc.Helpers;
|
||||
|
||||
namespace Yavsc.Controllers
|
||||
{
|
||||
[ServiceFilter(typeof(LanguageActionFilter)),AllowAnonymous]
|
||||
[ServiceFilter(typeof(LanguageActionFilter)), AllowAnonymous]
|
||||
public class AccountController : Controller
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
@ -49,7 +49,7 @@ namespace Yavsc.Controllers
|
||||
_smtpSettings = smtpSettings.Value;
|
||||
_twilioSettings = twilioSettings.Value;
|
||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||
|
||||
|
||||
}
|
||||
|
||||
[HttpGet(Constants.LoginPath)]
|
||||
@ -69,90 +69,84 @@ namespace Yavsc.Controllers
|
||||
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
[HttpPost(Constants.LoginPath)]
|
||||
public async Task<IActionResult> SignIn(SignInViewModel model)
|
||||
{
|
||||
if (Request.Method == "POST")
|
||||
{
|
||||
if (model.Provider=="LOCAL")
|
||||
if (model.Provider == "LOCAL")
|
||||
{
|
||||
return await Login(model);
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return Redirect(model.ReturnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(2, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
ModelState.AddModelError(string.Empty, "Unexpected behavior: something failed ... you could try again, or contact me ...");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Note: the "provider" parameter corresponds to the external
|
||||
// authentication provider choosen by the user agent.
|
||||
if (string.IsNullOrEmpty(model.Provider))
|
||||
{
|
||||
_logger.LogWarning("Provider not specified");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
|
||||
if (!_signInManager.GetExternalAuthenticationSchemes().Any(x => x.AuthenticationScheme == model.Provider))
|
||||
{
|
||||
_logger.LogWarning($"Provider not found : {model.Provider}");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
|
||||
// Instruct the middleware corresponding to the requested external identity
|
||||
// provider to redirect the user agent to its own authorization endpoint.
|
||||
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
|
||||
|
||||
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
||||
// will be redirected to after a successful authentication and not
|
||||
// the redirect_uri of the requesting client application.
|
||||
if (string.IsNullOrEmpty(model.ReturnUrl))
|
||||
{
|
||||
_logger.LogWarning("ReturnUrl not specified");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
// Note: this still is not the redirect uri given to the third party provider, at building the challenge.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = model.ReturnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(model.Provider, redirectUrl);
|
||||
// var properties = new AuthenticationProperties{RedirectUri=ReturnUrl};
|
||||
return new ChallengeResult(model.Provider, properties);
|
||||
|
||||
}
|
||||
}
|
||||
model.ExternalProviders = HttpContext.GetExternalProviders();
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost(Constants.ExternalLoginPath)]
|
||||
public IActionResult ExternalLogin(string Provider, string ReturnUrl)
|
||||
{
|
||||
// Note: the "provider" parameter corresponds to the external
|
||||
// authentication provider choosen by the user agent.
|
||||
if (string.IsNullOrEmpty(Provider))
|
||||
{
|
||||
_logger.LogWarning("Provider not specified");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
|
||||
if (!_signInManager.GetExternalAuthenticationSchemes().Any(x => x.AuthenticationScheme == Provider))
|
||||
{
|
||||
_logger.LogWarning($"Provider not found : {Provider}");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
|
||||
// Instruct the middleware corresponding to the requested external identity
|
||||
// provider to redirect the user agent to its own authorization endpoint.
|
||||
// Note: the authenticationScheme parameter must match the value configured in Startup.cs
|
||||
|
||||
// Note: the "returnUrl" parameter corresponds to the endpoint the user agent
|
||||
// will be redirected to after a successful authentication and not
|
||||
// the redirect_uri of the requesting client application.
|
||||
if (string.IsNullOrEmpty(ReturnUrl))
|
||||
{
|
||||
_logger.LogWarning("ReturnUrl not specified");
|
||||
return HttpBadRequest();
|
||||
}
|
||||
// Note: this still is not the redirect uri given to the third party provider, at building the challenge.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = ReturnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(Provider, redirectUrl);
|
||||
// var properties = new AuthenticationProperties{RedirectUri=ReturnUrl};
|
||||
return new ChallengeResult(Provider, properties);
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Login(SignInViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
// This doesn't count login failures towards account lockout
|
||||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
||||
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
|
||||
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return Redirect(model.ReturnUrl);
|
||||
}
|
||||
if (result.RequiresTwoFactor)
|
||||
{
|
||||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe });
|
||||
}
|
||||
if (result.IsLockedOut)
|
||||
{
|
||||
_logger.LogWarning(2, "User account locked out.");
|
||||
return View("Lockout");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, something failed, redisplay form
|
||||
ModelState.AddModelError(string.Empty, "Unexpected behavior: something failed ... you could try again, or contact me ...");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Register
|
||||
[HttpGet]
|
||||
@ -198,7 +192,7 @@ namespace Yavsc.Controllers
|
||||
{
|
||||
await _signInManager.SignOutAsync();
|
||||
_logger.LogInformation(4, "User logged out.");
|
||||
if (returnUrl==null) return RedirectToAction(nameof(HomeController.Index), "Home");
|
||||
if (returnUrl == null) return RedirectToAction(nameof(HomeController.Index), "Home");
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
|
||||
@ -545,7 +539,7 @@ namespace Yavsc.Controllers
|
||||
return await _userManager.FindByIdAsync(HttpContext.User.GetUserId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
@ -29,6 +29,10 @@ namespace Yavsc.Controllers
|
||||
{
|
||||
return View();
|
||||
}
|
||||
public IActionResult AboutMarkdown()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Contact()
|
||||
{
|
||||
|
@ -167,7 +167,6 @@ namespace Yavsc.Controllers
|
||||
{
|
||||
primaryIdentity.AddClaim(new Claim("urn:oauth:scope", scope));
|
||||
}
|
||||
_logger.LogWarning("Logging user {principal} against {OAuthDefaults.AuthenticationType}");
|
||||
await authentication.SignInAsync(OAuthDefaults.AuthenticationType, principal);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Request.Form["submit.Deny"]))
|
||||
|
@ -3,6 +3,7 @@ using System.Security.Claims;
|
||||
using Microsoft.AspNet.Authentication;
|
||||
using Microsoft.AspNet.Authentication.Cookies;
|
||||
using Microsoft.AspNet.Authentication.Facebook;
|
||||
using Microsoft.AspNet.Authentication.JwtBearer;
|
||||
using Microsoft.AspNet.Authentication.OAuth;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
@ -12,7 +13,9 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.WebEncoders;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using OAuth.AspNet.Tokens;
|
||||
using Yavsc.Auth;
|
||||
using Yavsc.Extensions;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace Yavsc
|
||||
@ -26,6 +29,8 @@ namespace Yavsc
|
||||
public static FacebookOptions FacebookAppOptions { get; private set; }
|
||||
public static OAuthAuthorizationServerOptions OAuthServerAppOptions { get; private set; }
|
||||
|
||||
public static OAuthOptions OAuthClientOptions { get; set; }
|
||||
|
||||
public static YavscGoogleOptions YavscGoogleAppOptions { get; private set; }
|
||||
public static MonoDataProtectionProvider ProtectionProvider { get; private set; }
|
||||
|
||||
@ -38,23 +43,7 @@ namespace Yavsc
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<OAuth2AppSettings>), typeof(OptionsManager<OAuth2AppSettings>)));
|
||||
// used by the YavscGoogleOAuth middelware (TODO drop it)
|
||||
services.AddTransient<Microsoft.Extensions.WebEncoders.UrlEncoder, UrlEncoder>();
|
||||
/* Obsolete:
|
||||
var keyParamsFileInfo =
|
||||
new FileInfo(Configuration["DataProtection:RSAParamFile"]);
|
||||
var keyParams = (keyParamsFileInfo.Exists) ?
|
||||
RSAKeyUtils.GetKeyParameters(keyParamsFileInfo.Name) :
|
||||
RSAKeyUtils.GenerateKeyAndSave(keyParamsFileInfo.Name);
|
||||
key = new RsaSecurityKey(keyParams);
|
||||
|
||||
services.Configure<TokenAuthOptions>(
|
||||
to =>
|
||||
{
|
||||
to.Audience = Configuration["Site:Audience"];
|
||||
to.Issuer = Configuration["Site:Authority"];
|
||||
to.SigningCredentials =
|
||||
new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature);
|
||||
}
|
||||
); */
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.SignInScheme = Constants.ExternalAuthenticationSheme;
|
||||
@ -70,7 +59,7 @@ namespace Yavsc
|
||||
IdentityAppOptions = option;
|
||||
option.User.AllowedUserNameCharacters += " ";
|
||||
option.User.RequireUniqueEmail = true;
|
||||
// option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
// option.Cookies.ApplicationCookieAuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
option.Cookies.ApplicationCookie.LoginPath = "/signin";
|
||||
// option.Cookies.ApplicationCookie.AuthenticationScheme = Constants.ApplicationAuthenticationSheme;
|
||||
/*
|
||||
@ -94,93 +83,119 @@ namespace Yavsc
|
||||
;
|
||||
|
||||
}
|
||||
private void ConfigureOAuthApp(IApplicationBuilder app)
|
||||
private void ConfigureOAuthApp(IApplicationBuilder app, SiteSettings settings)
|
||||
{
|
||||
// External authentication shared cookie:
|
||||
app.UseCookieAuthentication(options =>
|
||||
{
|
||||
ExternalCookieAppOptions = options;
|
||||
options.AuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
options.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1));
|
||||
});
|
||||
|
||||
app.UseIdentity();
|
||||
app.UseOAuthAuthorizationServer(
|
||||
|
||||
options =>
|
||||
{
|
||||
OAuthServerAppOptions = options;
|
||||
options.AuthorizeEndpointPath = new PathString(Constants.AuthorizePath.Substring(1));
|
||||
options.TokenEndpointPath = new PathString(Constants.TokenPath.Substring(1));
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
options.AllowInsecureHttp = true;
|
||||
options.AuthenticationScheme = OAuthDefaults.AuthenticationType;
|
||||
options =>
|
||||
{
|
||||
OAuthServerAppOptions = options;
|
||||
options.AuthorizeEndpointPath = new PathString(Constants.AuthorizePath.Substring(1));
|
||||
options.TokenEndpointPath = new PathString(Constants.TokenPath.Substring(1));
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
options.AllowInsecureHttp = true;
|
||||
options.AuthenticationScheme = OAuthDefaults.AuthenticationType;
|
||||
options.TokenDataProtector = ProtectionProvider.CreateProtector("Bearer protection");
|
||||
|
||||
options.Provider = new OAuthAuthorizationServerProvider
|
||||
{
|
||||
OnValidateClientRedirectUri = ValidateClientRedirectUri,
|
||||
OnValidateClientAuthentication = ValidateClientAuthentication,
|
||||
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
|
||||
OnGrantClientCredentials = GrantClientCredetails
|
||||
};
|
||||
options.Provider = new OAuthAuthorizationServerProvider
|
||||
{
|
||||
OnValidateClientRedirectUri = ValidateClientRedirectUri,
|
||||
OnValidateClientAuthentication = ValidateClientAuthentication,
|
||||
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
|
||||
OnGrantClientCredentials = GrantClientCredetails
|
||||
};
|
||||
|
||||
options.AuthorizationCodeProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateAuthenticationCode,
|
||||
OnReceive = ReceiveAuthenticationCode,
|
||||
};
|
||||
options.AuthorizationCodeProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateAuthenticationCode,
|
||||
OnReceive = ReceiveAuthenticationCode,
|
||||
};
|
||||
|
||||
options.RefreshTokenProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateRefreshToken,
|
||||
OnReceive = ReceiveRefreshToken,
|
||||
};
|
||||
options.RefreshTokenProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateRefreshToken,
|
||||
OnReceive = ReceiveRefreshToken,
|
||||
};
|
||||
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.AutomaticChallenge = true;
|
||||
}
|
||||
);
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.AutomaticChallenge = true;
|
||||
}
|
||||
);
|
||||
|
||||
app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"),
|
||||
branch =>
|
||||
{
|
||||
branch.UseJwtBearerAuthentication(
|
||||
options =>
|
||||
{
|
||||
options.AuthenticationScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.SecurityTokenValidators.Clear();
|
||||
options.SecurityTokenValidators.Add(new TicketDataFormatTokenValidator(
|
||||
ProtectionProvider
|
||||
));
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
app.UseWhen(context => !context.Request.Path.StartsWithSegments("/api"),
|
||||
branch =>
|
||||
{
|
||||
// External authentication shared cookie:
|
||||
branch.UseCookieAuthentication(options =>
|
||||
{
|
||||
ExternalCookieAppOptions = options;
|
||||
options.AuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
// TODO implement an access denied page
|
||||
options.AccessDeniedPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
});
|
||||
|
||||
|
||||
|
||||
var gvents = new OAuthEvents();
|
||||
YavscGoogleAppOptions = new YavscGoogleOptions
|
||||
{
|
||||
ClientId = Configuration["Authentication:Google:ClientId"],
|
||||
ClientSecret = Configuration["Authentication:Google:ClientSecret"],
|
||||
AccessType = "offline",
|
||||
SaveTokensAsClaims = true,
|
||||
UserInformationEndpoint = "https://www.googleapis.com/plus/v1/people/me",
|
||||
Events = new OAuthEvents
|
||||
{
|
||||
OnCreatingTicket = async context =>
|
||||
{
|
||||
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
|
||||
.CreateScope())
|
||||
{
|
||||
var gcontext = context as GoogleOAuthCreatingTicketContext;
|
||||
context.Identity.AddClaim(new Claim(YavscClaimTypes.GoogleUserId, gcontext.GoogleUserId));
|
||||
var service =
|
||||
serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||
await service.StoreTokenAsync(gcontext.GoogleUserId, context.TokenResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
YavscGoogleAppOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||
branch.UseMiddleware<Yavsc.Auth.GoogleMiddleware>(YavscGoogleAppOptions);
|
||||
|
||||
// Facebook
|
||||
branch.UseFacebookAuthentication(options =>
|
||||
{
|
||||
FacebookAppOptions = options;
|
||||
options.AppId = Configuration["Authentication:Facebook:AppId"];
|
||||
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
|
||||
options.Scope.Add("email");
|
||||
options.UserInformationEndpoint = "https://graph.facebook.com/v2.5/me?fields=id,name,email,first_name,last_name";
|
||||
});
|
||||
});
|
||||
|
||||
app.UseIdentity();
|
||||
|
||||
var gvents = new OAuthEvents();
|
||||
YavscGoogleAppOptions = new YavscGoogleOptions
|
||||
{
|
||||
ClientId = Configuration["Authentication:Google:ClientId"],
|
||||
ClientSecret = Configuration["Authentication:Google:ClientSecret"],
|
||||
AccessType = "offline",
|
||||
SaveTokensAsClaims = true,
|
||||
UserInformationEndpoint = "https://www.googleapis.com/plus/v1/people/me",
|
||||
Events = new OAuthEvents
|
||||
{
|
||||
OnCreatingTicket = async context =>
|
||||
{
|
||||
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>()
|
||||
.CreateScope())
|
||||
{
|
||||
var gcontext = context as GoogleOAuthCreatingTicketContext;
|
||||
context.Identity.AddClaim(new Claim(YavscClaimTypes.GoogleUserId, gcontext.GoogleUserId));
|
||||
var service =
|
||||
serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
|
||||
await service.StoreTokenAsync(gcontext.GoogleUserId, context.TokenResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
YavscGoogleAppOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||
app.UseMiddleware<Yavsc.Auth.GoogleMiddleware>(YavscGoogleAppOptions);
|
||||
|
||||
// Facebook
|
||||
app.UseFacebookAuthentication(options =>
|
||||
{
|
||||
FacebookAppOptions = options;
|
||||
options.AppId = Configuration["Authentication:Facebook:AppId"];
|
||||
options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
|
||||
options.Scope.Add("email");
|
||||
options.UserInformationEndpoint = "https://graph.facebook.com/v2.5/me?fields=id,name,email,first_name,last_name";
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using Yavsc.Helpers;
|
||||
@ -73,17 +76,37 @@ namespace Yavsc
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
|
||||
private async Task<Task> GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
|
||||
{
|
||||
ApplicationUser user = null;
|
||||
logger.LogWarning($"GrantResourceOwnerCredentials task ... {context.UserName}");
|
||||
|
||||
// var user = ValidateUser(context.UserName, context.Password)
|
||||
|
||||
ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x))));
|
||||
using (var usermanager = context.HttpContext.ApplicationServices.GetRequiredService<UserManager<ApplicationUser>>())
|
||||
{
|
||||
user = await usermanager.FindByNameAsync(context.UserName);
|
||||
if (await usermanager.CheckPasswordAsync(user,context.Password))
|
||||
{
|
||||
|
||||
var claims = new List<Claim>(
|
||||
context.Scope.Select(x => new Claim("urn:oauth:scope", x))
|
||||
);
|
||||
claims.Add(new Claim(ClaimTypes.NameIdentifier,user.Id));
|
||||
claims.Add(new Claim(ClaimTypes.Email,user.Email));
|
||||
claims.AddRange((await usermanager.GetRolesAsync(user)).Select(
|
||||
r => new Claim(ClaimTypes.Role,r)
|
||||
) );
|
||||
ClaimsPrincipal principal = new ClaimsPrincipal(
|
||||
new ClaimsIdentity(
|
||||
new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType),
|
||||
claims)
|
||||
);
|
||||
// TODO set a NameIdentifier, roles and scopes claims
|
||||
context.HttpContext.User = principal;
|
||||
|
||||
context.Validated(principal);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
@ -117,6 +140,9 @@ namespace Yavsc
|
||||
{
|
||||
var uid = context.Ticket.Principal.GetUserId();
|
||||
logger.LogInformation($"CreateRefreshToken for {uid}");
|
||||
foreach (var c in context.Ticket.Principal.Claims)
|
||||
logger.LogInformation($"| User claim: {c.Type} {c.Value}");
|
||||
|
||||
context.SetToken(context.SerializeTicket());
|
||||
}
|
||||
|
||||
@ -124,6 +150,8 @@ namespace Yavsc
|
||||
{
|
||||
var uid = context.Ticket.Principal.GetUserId();
|
||||
logger.LogInformation($"ReceiveRefreshToken for {uid}");
|
||||
foreach (var c in context.Ticket.Principal.Claims)
|
||||
logger.LogInformation($"| User claim: {c.Type} {c.Value}");
|
||||
context.DeserializeTicket(context.Token);
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,9 @@ namespace Yavsc
|
||||
public partial class Startup
|
||||
{
|
||||
public static string ConnectionString { get; private set; }
|
||||
public static string Authority { get; private set; }
|
||||
public static string Audience { get; private set; }
|
||||
|
||||
private static ILogger logger;
|
||||
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
|
||||
{
|
||||
@ -268,14 +271,16 @@ namespace Yavsc
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
app.UseIISPlatformHandler(options =>
|
||||
{
|
||||
options.AuthenticationDescriptions.Clear();
|
||||
options.AutomaticAuthentication = false;
|
||||
});
|
||||
|
||||
ConfigureOAuthApp(app);
|
||||
Authority = siteSettings.Value.Authority;
|
||||
Audience = siteSettings.Value.Audience;
|
||||
|
||||
ConfigureOAuthApp(app,siteSettings.Value);
|
||||
|
||||
ConfigureFileServerApp(app,siteSettings.Value,env);
|
||||
|
||||
|
21
Yavsc/ViewModels/Account/Me.cs
Normal file
21
Yavsc/ViewModels/Account/Me.cs
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Yavsc.Models.Auth
|
||||
{
|
||||
public class Me {
|
||||
public Me(ApplicationUser user)
|
||||
{
|
||||
Id = user.Id;
|
||||
GivenName = user.UserName;
|
||||
Emails = new string [] { user.Email } ;
|
||||
}
|
||||
public string Id { get; set; }
|
||||
public string GivenName { get; set; }
|
||||
public string[] Emails { get; set; }
|
||||
/// <summary>
|
||||
/// Known as profile, could point to an avatar
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string Url { get; set; }
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -108,7 +108,7 @@ public class BlogViewHandler : AuthorizationHandler<ViewRequirement, Blog>
|
||||
protected override void Handle(AuthorizationContext context, PrivateChatEntryRequirement requirement)
|
||||
{
|
||||
if (!context.User.HasClaim(c => c.Type == "TemporaryBadgeExpiry" &&
|
||||
c.Issuer == Constants.Issuer))
|
||||
c.Issuer == Startup.Authority))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -116,7 +116,7 @@ public class BlogViewHandler : AuthorizationHandler<ViewRequirement, Blog>
|
||||
var temporaryBadgeExpiry =
|
||||
Convert.ToDateTime(context.User.FindFirst(
|
||||
c => c.Type == "TemporaryBadgeExpiry" &&
|
||||
c.Issuer == Constants.Issuer).Value);
|
||||
c.Issuer == Startup.Authority).Value);
|
||||
|
||||
if (temporaryBadgeExpiry > DateTime.Now)
|
||||
{
|
||||
@ -130,7 +130,7 @@ public class BlogViewHandler : AuthorizationHandler<ViewRequirement, Blog>
|
||||
protected override void Handle(AuthorizationContext context, PrivateChatEntryRequirement requirement)
|
||||
{
|
||||
if (!context.User.HasClaim(c => c.Type == "BadgeNumber" &&
|
||||
c.Issuer == Constants.Issuer))
|
||||
c.Issuer == Startup.Authority))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -4,10 +4,16 @@
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
|
||||
<markdown>
|
||||
Quelques extension à un Markdown de base :
|
||||
Quelques extensions à un Markdown de base :
|
||||
|
||||
* les video et audio
|
||||
* le tag bug = Bug#542
|
||||
* le tag annonce = A#542
|
||||
* les video et audio: ``
|
||||
|
||||

|
||||
|
||||
à faire:
|
||||
|
||||
* le tag "Numéro de ticket": `Ticket#6854`
|
||||
* le tag "Titre d'article": `#1_great_title`
|
||||
* le tag "User" = `@@(007, it'sme)` ou `@@james`
|
||||
|
||||
</markdown>
|
||||
|
@ -56,23 +56,23 @@
|
||||
<hr/>
|
||||
<h2 class="lead text-left">@SR["Use another service to log in"]:</h2>
|
||||
@if (Model.ExternalProviders.Count() == 0)
|
||||
{
|
||||
<div>
|
||||
<p>
|
||||
There are no external authentication services configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
|
||||
for details on setting up this ASP.NET application to support logging in via external services.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var description in Model.ExternalProviders) {
|
||||
<form action="@Constants.ExternalLoginPath" method="post">
|
||||
{
|
||||
<div>
|
||||
<p>
|
||||
There are no external authentication services configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
|
||||
for details on setting up this ASP.NET application to support logging in via external services.
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var description in Model.ExternalProviders) {
|
||||
<form action="@Constants.LoginPath" method="post">
|
||||
<input type="hidden" name="Provider" value="@description.AuthenticationScheme" />
|
||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||
<button class="btn btn-lg btn-success" type="submit" name="Submit.Login">@SR["Connect using"] @description.DisplayName</button>
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
@ -74,7 +74,6 @@
|
||||
"Microsoft.AspNet.SignalR.JS": "2.2.0",
|
||||
"Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-*",
|
||||
"Microsoft.AspNet.WebSockets.Server": "1.0.0-rc1-final",
|
||||
"Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-*",
|
||||
"Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-*",
|
||||
@ -105,7 +104,8 @@
|
||||
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-rc1-final",
|
||||
"PayPalCoreSDK": "1.7.1",
|
||||
"PayPalButtonManagerSDK": "2.10.109",
|
||||
"Microsoft.AspNet.Owin": "1.0.0-rc1-final"
|
||||
"Microsoft.AspNet.Owin": "1.0.0-rc1-final",
|
||||
"Microsoft.AspNet.Authentication.OAuth": "1.0.0-rc1-final"
|
||||
},
|
||||
"commands": {
|
||||
"web": "Microsoft.AspNet.Server.Kestrel --server.urls http://*:5000",
|
||||
|
File diff suppressed because it is too large
Load Diff
BIN
Yavsc/wwwroot/images/testVideo.mp4
Normal file
BIN
Yavsc/wwwroot/images/testVideo.mp4
Normal file
Binary file not shown.
@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
@ -8,11 +11,35 @@ namespace testOauthClient.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
[HttpGet]
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> GetUserInfo(CancellationToken cancellationToken)
|
||||
{
|
||||
using (var client = new HttpClient()) {
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://dev.pschneider.fr/api/me");
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
|
||||
|
||||
var response = await client.SendAsync(request, cancellationToken);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
return View("Index", model: await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
}
|
||||
protected string AccessToken {
|
||||
get {
|
||||
var claim = HttpContext.User?.FindFirst("access_token");
|
||||
if (claim == null) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return claim.Value;
|
||||
}
|
||||
}
|
||||
public IActionResult About()
|
||||
{
|
||||
ViewData["Message"] = "Your application description page.";
|
||||
|
@ -78,7 +78,7 @@ namespace testOauthClient
|
||||
options.ClientId="21d8bd1b-4aed-4fcb-9ed9-00b43f6a8169";
|
||||
options.ClientSecret="blih";
|
||||
options.Scope.Add("profile");
|
||||
options.SaveTokensAsClaims = true;
|
||||
// options.SaveTokensAsClaims = true;
|
||||
options.UserInformationEndpoint = "http://dev.pschneider.fr/api/me";
|
||||
}
|
||||
);
|
||||
|
@ -16,7 +16,7 @@
|
||||
<h3>Message received from the resource controller: @Model</h3>
|
||||
}
|
||||
|
||||
<form action="~/" method="post">
|
||||
<form action="~/Home/GetUserInfo" method="post">
|
||||
<button class="btn btn-lg btn-warning" type="submit">Query the resource controller</button>
|
||||
</form>
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
"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",
|
||||
|
Reference in New Issue
Block a user