oauth
This commit is contained in:
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.IdentityModel.Tokens;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
[Obsolete("Use OAuth2AppSettings instead")]
|
||||
public class TokenAuthOptions
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -2,9 +2,17 @@ namespace Yavsc
|
||||
{
|
||||
using Yavsc.Models.Auth;
|
||||
|
||||
public static class Constants
|
||||
public static class Constants
|
||||
{
|
||||
public const string RememberMeCookieName = "Berme";
|
||||
public const string AccessDeniedPath = "~/forbidden";
|
||||
public const string AuthorizePath = "~/authorize";
|
||||
public const string TokenPath = "~/token";
|
||||
public const string LoginPath = "~/signin";
|
||||
public const string LogoutPath = "~/signout";
|
||||
public const string MePath = "~/api/Me";
|
||||
|
||||
public const string ExternalAuthenticationSheme = "External";
|
||||
public const string ApplicationAuthenticationSheme = "Server";
|
||||
public static readonly Scope[] SiteScopes = {
|
||||
new Scope { Id = "profile", Description = "Your profile informations" },
|
||||
new Scope { Id = "book" , Description ="Your booking interface"},
|
||||
@ -40,8 +48,6 @@ namespace Yavsc
|
||||
|
||||
public const string UserNameRegExp = @"^[a-zA-Z][a-zA-Z0-9 ]*$";
|
||||
|
||||
public const string AuthenticationEndPath = "/signin";
|
||||
public const string TokenEndPath = "/token";
|
||||
|
||||
public const string KeyProtectorPurpose = "OAuth.AspNet.AuthServer";
|
||||
|
||||
|
@ -50,18 +50,62 @@ namespace Yavsc.Controllers
|
||||
_twilioSettings = twilioSettings.Value;
|
||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||
}
|
||||
|
||||
[HttpGet("~/login")]
|
||||
public IActionResult Login(string returnUrl)
|
||||
[HttpGet(Constants.LoginPath)]
|
||||
public ActionResult Login(string returnUrl = null)
|
||||
{
|
||||
return View("SignIn", new LoginViewModel {
|
||||
// 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 against the third
|
||||
// party identity provider.
|
||||
return View("Login", new LoginViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl,
|
||||
ExternalProviders = HttpContext.GetExternalProviders()
|
||||
});
|
||||
});
|
||||
/* Note: When using an external login provider, redirect the query :
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(OpenIdConnectDefaults.AuthenticationScheme, returnUrl);
|
||||
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||
*/
|
||||
}
|
||||
|
||||
[HttpPost("~/login")]
|
||||
public async Task<IActionResult> SignIn(LoginViewModel model)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
[HttpPost(Constants.LoginPath)]
|
||||
public async Task<IActionResult> Login(LoginViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
@ -92,6 +136,7 @@ namespace Yavsc.Controllers
|
||||
ModelState.AddModelError(string.Empty, "Unexpected behavior: something failed ... you could try again, or contact me ...");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/Register
|
||||
[HttpGet]
|
||||
@ -131,7 +176,7 @@ namespace Yavsc.Controllers
|
||||
|
||||
//
|
||||
// POST: /Account/LogOff
|
||||
[HttpPost]
|
||||
[HttpPost(Constants.LogoutPath)]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> LogOff(string returnUrl = null)
|
||||
{
|
||||
@ -140,18 +185,6 @@ namespace Yavsc.Controllers
|
||||
if (returnUrl==null) return RedirectToAction(nameof(HomeController.Index), "Home");
|
||||
return Redirect(returnUrl);
|
||||
}
|
||||
|
||||
//
|
||||
// POST: /Account/ExternalLogin
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult ExternalLogin(string provider, string returnUrl = null)
|
||||
{
|
||||
// Request a redirect to the external login provider.
|
||||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
return new ChallengeResult(provider, properties);
|
||||
}
|
||||
|
||||
//
|
||||
// GET: /Account/ExternalLoginCallback
|
||||
|
@ -1,34 +1,40 @@
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.DataProtection.KeyManagement;
|
||||
using Microsoft.AspNet.Http.Authentication;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.Data.Entity;
|
||||
using Microsoft.AspNet.WebUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Yavsc.Extensions;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.ViewModels.Account;
|
||||
|
||||
namespace Yavsc.Controllers
|
||||
{
|
||||
public class TokenResponse
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public int expires_in { get; set; }
|
||||
public string grant_type { get; set; }
|
||||
|
||||
public int entity_id { get; set; }
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
public class OAuthController : Controller
|
||||
{
|
||||
ApplicationDbContext _context;
|
||||
UserManager<ApplicationUser> _userManager;
|
||||
|
||||
|
||||
SiteSettings _siteSettings;
|
||||
|
||||
ILogger _logger;
|
||||
private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
private TokenAuthOptions _tokenOptions;
|
||||
|
||||
public OAuthController(ApplicationDbContext context, SignInManager<ApplicationUser> signInManager, IKeyManager keyManager,
|
||||
IOptions<TokenAuthOptions> tokenOptions,
|
||||
UserManager<ApplicationUser> userManager,
|
||||
IOptions<SiteSettings> siteSettings,
|
||||
ILoggerFactory loggerFactory
|
||||
@ -37,90 +43,61 @@ namespace Yavsc.Controllers
|
||||
_siteSettings = siteSettings.Value;
|
||||
_context = context;
|
||||
_signInManager = signInManager;
|
||||
_tokenOptions = tokenOptions.Value;
|
||||
_userManager = userManager;
|
||||
_logger = loggerFactory.CreateLogger<OAuthController>();
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("~/signin")]
|
||||
public ActionResult SignIn(string returnUrl = null)
|
||||
{
|
||||
// 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 against the third
|
||||
// party identity provider.
|
||||
return View("SignIn", new LoginViewModel
|
||||
{
|
||||
ReturnUrl = returnUrl,
|
||||
ExternalProviders = HttpContext.GetExternalProviders()
|
||||
});
|
||||
/* Note: When using an external login provider, redirect the query :
|
||||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(OpenIdConnectDefaults.AuthenticationScheme, returnUrl);
|
||||
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, properties);
|
||||
*/
|
||||
}
|
||||
|
||||
[HttpGet("~/authenticate")]
|
||||
public ActionResult Authenticate(string returnUrl = null)
|
||||
{
|
||||
return SignIn(returnUrl);
|
||||
}
|
||||
|
||||
[HttpGet("~/forbidden")]
|
||||
|
||||
[HttpGet(Constants.AccessDeniedPath)]
|
||||
public ActionResult Forbidden(string returnUrl = null)
|
||||
{
|
||||
return View("Forbidden",returnUrl);
|
||||
return View("Forbidden", returnUrl);
|
||||
}
|
||||
|
||||
[HttpPost("~/signin")]
|
||||
public IActionResult SignIn(string Provider, string ReturnUrl)
|
||||
|
||||
/*
|
||||
private async Task<string> GetToken(string purpose, string userid, DateTime? expires)
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
// Here, you should create or look up an identity for the user which is being authenticated.
|
||||
// For now, just creating a simple generic identity.
|
||||
var identuser = await _userManager.FindByIdAsync(userid);
|
||||
|
||||
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();
|
||||
}
|
||||
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);
|
||||
return await _tokenProvider.GenerateAsync(purpose, _userManager, identuser);
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet("~/signout"), HttpPost("~/signout")]
|
||||
public async Task SignOut()
|
||||
/// <summary>
|
||||
/// Check if currently authenticated. Will throw an exception of some sort which shoudl be caught by a general
|
||||
/// exception handler and returned to the user as a 401, if not authenticated. Will return a fresh token if
|
||||
/// the user is authenticated, which will reset the expiry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet, HttpPost, Authorize]
|
||||
[Route("~/oauth/token")]
|
||||
public async Task<dynamic> Get()
|
||||
{
|
||||
// Instruct 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 (e.g Google or Facebook).
|
||||
|
||||
await HttpContext.Authentication.SignOutAsync("ServerCookie");
|
||||
}
|
||||
bool authenticated = false;
|
||||
string user = null;
|
||||
int entityId = -1;
|
||||
string token = null;
|
||||
DateTime? tokenExpires = default(DateTime?);
|
||||
var currentUser = User;
|
||||
if (currentUser != null)
|
||||
{
|
||||
authenticated = currentUser.Identity.IsAuthenticated;
|
||||
if (authenticated)
|
||||
{
|
||||
user = User.GetUserId();
|
||||
_logger.LogInformation($"authenticated user:{user}");
|
||||
|
||||
foreach (Claim c in currentUser.Claims) if (c.Type == "EntityID") entityId = Convert.ToInt32(c.Value);
|
||||
|
||||
tokenExpires = DateTime.UtcNow.AddMinutes(2);
|
||||
token = await GetToken("id_token", user, tokenExpires);
|
||||
return new TokenResponse { access_token = token, expires_in = 3400, entity_id = entityId };
|
||||
}
|
||||
}
|
||||
return new { authenticated = false };
|
||||
} */
|
||||
|
||||
|
||||
[HttpGet("~/api/getclaims"), Produces("application/json")]
|
||||
@ -140,14 +117,66 @@ namespace Yavsc.Controllers
|
||||
return Ok(claims);
|
||||
}
|
||||
|
||||
protected virtual Task<Application> GetApplicationAsync(string identifier, CancellationToken cancellationToken)
|
||||
[HttpGet(Constants.AuthorizePath)]
|
||||
public async Task<ActionResult> Authorize()
|
||||
{
|
||||
// Retrieve the application details corresponding to the requested client_id.
|
||||
return (from application in _context.Applications
|
||||
where application.ApplicationID == identifier
|
||||
select application).SingleOrDefaultAsync(cancellationToken);
|
||||
if (Response.StatusCode != 200)
|
||||
{
|
||||
return View("AuthorizeError");
|
||||
}
|
||||
|
||||
AuthenticationManager authentication = Request.HttpContext.Authentication;
|
||||
|
||||
ClaimsPrincipal principal = await authentication.AuthenticateAsync(Constants.ApplicationAuthenticationSheme);
|
||||
|
||||
if (principal == null)
|
||||
{
|
||||
await authentication.ChallengeAsync(Constants.ApplicationAuthenticationSheme);
|
||||
|
||||
if (Response.StatusCode == 200)
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
return new HttpStatusCodeResult(Response.StatusCode);
|
||||
}
|
||||
|
||||
string[] scopes = { };
|
||||
|
||||
if (Request.QueryString.HasValue)
|
||||
{
|
||||
var queryStringComponents = QueryHelpers.ParseQuery(Request.QueryString.Value);
|
||||
|
||||
if (queryStringComponents.ContainsKey("scope"))
|
||||
scopes = queryStringComponents["scope"];
|
||||
}
|
||||
|
||||
if (Request.Method == "POST")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(Request.Form["submit.Grant"]))
|
||||
{
|
||||
principal = new ClaimsPrincipal(principal.Identities);
|
||||
|
||||
ClaimsIdentity primaryIdentity = (ClaimsIdentity)principal.Identity;
|
||||
|
||||
foreach (var scope in scopes)
|
||||
{
|
||||
primaryIdentity.AddClaim(new Claim("urn:oauth:scope", scope));
|
||||
}
|
||||
|
||||
await authentication.SignInAsync(OAuthDefaults.AuthenticationType, principal);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Request.Form["submit.Login"]))
|
||||
{
|
||||
await authentication.SignOutAsync(Constants.ApplicationAuthenticationSheme);
|
||||
|
||||
await authentication.ChallengeAsync(Constants.ApplicationAuthenticationSheme);
|
||||
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
}
|
||||
|
||||
return View(new AuthorisationView { Scopes = scopes } );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Yavsc.Auth;
|
||||
using Microsoft.AspNet.Identity;
|
||||
using Yavsc.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Yavsc.Controllers
|
||||
{
|
||||
[Produces("application/json"),AllowAnonymous]
|
||||
public class TokenController : Controller
|
||||
{
|
||||
private readonly TokenAuthOptions tokenOptions;
|
||||
private ILogger logger;
|
||||
UserManager<ApplicationUser> manager;
|
||||
SignInManager<ApplicationUser> signInManager;
|
||||
public class TokenResponse {
|
||||
public string access_token { get; set; }
|
||||
public int expires_in { get; set; }
|
||||
public string grant_type { get; set; }
|
||||
|
||||
public int entity_id { get; set; }
|
||||
}
|
||||
UserTokenProvider tokenProvider;
|
||||
|
||||
public TokenController( UserManager<ApplicationUser> userManager,
|
||||
SignInManager<ApplicationUser> signInManager,
|
||||
IOptions<TokenAuthOptions> token_options, ILoggerFactory loggerFactory, UserTokenProvider tokenProvider)
|
||||
{
|
||||
this.manager = userManager;
|
||||
this.tokenOptions = token_options.Value;
|
||||
this.signInManager = signInManager;
|
||||
this.tokenProvider = tokenProvider;
|
||||
//this.bearerOptions = options.Value;
|
||||
//this.signingCredentials = signingCredentials;
|
||||
logger = loggerFactory.CreateLogger<TokenController>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if currently authenticated. Will throw an exception of some sort which shoudl be caught by a general
|
||||
/// exception handler and returned to the user as a 401, if not authenticated. Will return a fresh token if
|
||||
/// the user is authenticated, which will reset the expiry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet,HttpPost,Authorize]
|
||||
[Route("~/api/token/get")]
|
||||
public async Task<dynamic> Get()
|
||||
{
|
||||
bool authenticated = false;
|
||||
string user = null;
|
||||
int entityId = -1;
|
||||
string token = null;
|
||||
DateTime? tokenExpires = default(DateTime?);
|
||||
var currentUser = User;
|
||||
if (currentUser != null)
|
||||
{
|
||||
authenticated = currentUser.Identity.IsAuthenticated;
|
||||
if (authenticated)
|
||||
{
|
||||
user = User.GetUserId();
|
||||
logger.LogInformation($"authenticated user:{user}");
|
||||
|
||||
foreach (Claim c in currentUser.Claims) if (c.Type == "EntityID") entityId = Convert.ToInt32(c.Value);
|
||||
|
||||
tokenExpires = DateTime.UtcNow.AddMinutes(2);
|
||||
token = await GetToken("id_token", user, tokenExpires);
|
||||
return new TokenResponse { access_token = token, expires_in = 3400, entity_id = entityId };
|
||||
}
|
||||
}
|
||||
return new { authenticated = false };
|
||||
}
|
||||
|
||||
public class AuthRequest
|
||||
{
|
||||
public string username { get; set; }
|
||||
public string password { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request a new token for a given username/password pair.
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPost,Route("~/api/token/post")]
|
||||
public async Task<IActionResult> Post(AuthRequest req)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return new BadRequestObjectResult(ModelState);
|
||||
// Obviously, at this point you need to validate the username and password against whatever system you wish.
|
||||
var signResult = await signInManager.PasswordSignInAsync(req.username, req.password,false,true);
|
||||
|
||||
if (signResult.Succeeded)
|
||||
{
|
||||
DateTime? expires = DateTime.UtcNow.AddMinutes(tokenOptions.ExpiresIn);
|
||||
var token = await GetToken("id_token",User.GetUserId(), expires);
|
||||
return Ok(new TokenResponse {access_token = token, expires_in = 3400, grant_type="id_token" });
|
||||
}
|
||||
return new BadRequestObjectResult(new { authenticated = false } ) ;
|
||||
}
|
||||
|
||||
private async Task<string> GetToken(string purpose, string userid, DateTime? expires)
|
||||
{
|
||||
// Here, you should create or look up an identity for the user which is being authenticated.
|
||||
// For now, just creating a simple generic identity.
|
||||
var identuser = await manager.FindByIdAsync(userid);
|
||||
|
||||
return await tokenProvider.GenerateAsync(purpose,manager,identuser);
|
||||
}
|
||||
}
|
||||
}
|
41
Yavsc/Startup/Startup.DataProtection.cs
Normal file
41
Yavsc/Startup/Startup.DataProtection.cs
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Microsoft.AspNet.DataProtection.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
|
||||
public partial class Startup
|
||||
{
|
||||
public void ConfigureProtectionServices(IServiceCollection services)
|
||||
{
|
||||
|
||||
services.AddDataProtection();
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IApplicationDiscriminator),
|
||||
typeof(SystemWebApplicationDiscriminator)));
|
||||
|
||||
services.ConfigureDataProtection(configure =>
|
||||
{
|
||||
configure.SetApplicationName(Configuration["Site:Title"]);
|
||||
configure.SetDefaultKeyLifetime(TimeSpan.FromDays(45));
|
||||
configure.PersistKeysToFileSystem(
|
||||
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
||||
});
|
||||
|
||||
}
|
||||
private sealed class SystemWebApplicationDiscriminator : IApplicationDiscriminator
|
||||
{
|
||||
private readonly Lazy<string> _lazyDiscriminator = new Lazy<string>(GetAppDiscriminatorCore);
|
||||
|
||||
public string Discriminator => _lazyDiscriminator.Value;
|
||||
|
||||
private static string GetAppDiscriminatorCore()
|
||||
{
|
||||
return HttpRuntime.AppDomainAppId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
174
Yavsc/Startup/Startup.OAuth.cs
Normal file
174
Yavsc/Startup/Startup.OAuth.cs
Normal file
@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNet.Authentication;
|
||||
using Microsoft.AspNet.Authentication.OAuth;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.WebEncoders;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
using Yavsc.Auth;
|
||||
using Yavsc.Models;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
|
||||
public partial class Startup
|
||||
{
|
||||
private void ConfigureOAuthServices(IServiceCollection services)
|
||||
{
|
||||
services.Configure<SharedAuthenticationOptions>(options => options.SignInScheme = Constants.ExternalAuthenticationSheme);
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.SignInScheme = Constants.ExternalAuthenticationSheme;
|
||||
});
|
||||
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);
|
||||
}
|
||||
); */
|
||||
}
|
||||
private void ConfigureOAuthApp(IApplicationBuilder app)
|
||||
{
|
||||
app.UseIdentity();
|
||||
// External authentication shared cookie:
|
||||
app.UseCookieAuthentication(options =>
|
||||
{
|
||||
options.AuthenticationScheme = Constants.ExternalAuthenticationSheme;
|
||||
options.AutomaticAuthenticate = false;
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
});
|
||||
|
||||
var gvents = new OAuthEvents();
|
||||
var googleOptions = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||
app.UseMiddleware<Yavsc.Auth.GoogleMiddleware>(googleOptions);
|
||||
|
||||
// Facebook
|
||||
app.UseFacebookAuthentication(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";
|
||||
});
|
||||
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
||||
{
|
||||
OnGetUserInformationAsync = async context =>
|
||||
{
|
||||
// Get the GitHub user
|
||||
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
|
||||
userRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
|
||||
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
HttpResponseMessage userResponse = await context.Backchannel.SendAsync(userRequest, context.HttpContext.RequestAborted);
|
||||
userResponse.EnsureSuccessStatusCode();
|
||||
var text = await userResponse.Content.ReadAsStringAsync();
|
||||
JObject user = JObject.Parse(text);
|
||||
|
||||
var identity = new ClaimsIdentity(
|
||||
context.Options.AuthenticationType,
|
||||
ClaimsIdentity.DefaultNameClaimType,
|
||||
ClaimsIdentity.DefaultRoleClaimType);
|
||||
|
||||
JToken value;
|
||||
var id = user.TryGetValue("id", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var userName = user.TryGetValue("login", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(userName))
|
||||
{
|
||||
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, userName, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var name = user.TryGetValue("name", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
identity.AddClaim(new Claim("urn:github:name", name, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var link = user.TryGetValue("url", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(link))
|
||||
{
|
||||
identity.AddClaim(new Claim("urn:github:url", link, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
|
||||
context.Identity = identity;
|
||||
}
|
||||
}; */
|
||||
app.UseOAuthAuthorizationServer(
|
||||
|
||||
options =>
|
||||
{
|
||||
options.AuthorizeEndpointPath = new PathString(Constants.AuthorizePath.Substring(1));
|
||||
options.TokenEndpointPath = new PathString(Constants.TokenPath.Substring(1));
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
|
||||
#if DEBUG
|
||||
options.AllowInsecureHttp = true;
|
||||
#endif
|
||||
|
||||
options.Provider = new OAuthAuthorizationServerProvider
|
||||
{
|
||||
OnValidateClientRedirectUri = ValidateClientRedirectUri,
|
||||
OnValidateClientAuthentication = ValidateClientAuthentication,
|
||||
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
|
||||
OnGrantClientCredentials = GrantClientCredetails
|
||||
};
|
||||
|
||||
options.AuthorizationCodeProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateAuthenticationCode,
|
||||
OnReceive = ReceiveAuthenticationCode,
|
||||
};
|
||||
|
||||
options.RefreshTokenProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateRefreshToken,
|
||||
OnReceive = ReceiveRefreshToken,
|
||||
};
|
||||
|
||||
options.AutomaticAuthenticate = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,11 @@
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IdentityModel.Tokens;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using System.Web;
|
||||
using System.Web.Optimization;
|
||||
using Microsoft.AspNet.Authentication;
|
||||
using Microsoft.AspNet.Authentication.OAuth;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.DataProtection.Infrastructure;
|
||||
using Microsoft.AspNet.Diagnostics;
|
||||
using Microsoft.AspNet.Hosting;
|
||||
using Microsoft.AspNet.Http;
|
||||
@ -27,13 +21,11 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.OptionsModel;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Microsoft.Extensions.WebEncoders;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
using Yavsc.Auth;
|
||||
using Yavsc.Formatters;
|
||||
using Yavsc.Models;
|
||||
using Yavsc.Services;
|
||||
using OAuth.AspNet.AuthServer;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
@ -41,8 +33,6 @@ namespace Yavsc
|
||||
public partial class Startup
|
||||
{
|
||||
public static string ConnectionString { get; private set; }
|
||||
private RsaSecurityKey key;
|
||||
|
||||
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
|
||||
{
|
||||
// Set up configuration sources.
|
||||
@ -97,7 +87,6 @@ namespace Yavsc
|
||||
new CultureInfo("fr")
|
||||
};
|
||||
|
||||
|
||||
// You must explicitly state which cultures your application supports.
|
||||
// These are the cultures the app supports for formatting numbers, dates, etc.
|
||||
options.SupportedCultures = supportedCultures;
|
||||
@ -118,54 +107,17 @@ namespace Yavsc
|
||||
// return new ProviderCultureResult("en");
|
||||
//}));
|
||||
});
|
||||
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<SharedAuthenticationOptions>(options =>
|
||||
{
|
||||
options.SignInScheme = "ServerCookie";
|
||||
});
|
||||
|
||||
services.Configure<TokenAuthOptions>(
|
||||
to =>
|
||||
{
|
||||
to.Audience = Configuration["Site:Audience"];
|
||||
to.Issuer = Configuration["Site:Authority"];
|
||||
to.SigningCredentials =
|
||||
new SigningCredentials(key, SecurityAlgorithms.RsaSha256Signature);
|
||||
}
|
||||
);
|
||||
|
||||
ConfigureOAuthServices(services);
|
||||
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SiteSettings>), typeof(OptionsManager<SiteSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<SmtpSettings>), typeof(OptionsManager<SmtpSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<GoogleAuthSettings>), typeof(OptionsManager<GoogleAuthSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<CompanyInfoSettings>), typeof(OptionsManager<CompanyInfoSettings>)));
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<OAuth2AppSettings>), typeof(OptionsManager<OAuth2AppSettings>)));
|
||||
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IOptions<TokenAuthOptions>), typeof(OptionsManager<TokenAuthOptions>)));
|
||||
// DataProtection
|
||||
ConfigureProtectionServices(services);
|
||||
|
||||
|
||||
services.AddTransient<Microsoft.Extensions.WebEncoders.UrlEncoder, UrlEncoder>();
|
||||
services.AddDataProtection();
|
||||
services.Add(ServiceDescriptor.Singleton(typeof(IApplicationDiscriminator),
|
||||
typeof(SystemWebApplicationDiscriminator)));
|
||||
|
||||
services.ConfigureDataProtection(configure =>
|
||||
{
|
||||
configure.SetApplicationName(Configuration["Site:Title"]);
|
||||
configure.SetDefaultKeyLifetime(TimeSpan.FromDays(45));
|
||||
configure.PersistKeysToFileSystem(
|
||||
new DirectoryInfo(Configuration["DataProtection:Keys:Dir"]));
|
||||
});
|
||||
|
||||
services.AddAuthentication(
|
||||
op => op.SignInScheme = "ServerCookie"
|
||||
);
|
||||
// Add framework services.
|
||||
services.AddEntityFramework()
|
||||
.AddNpgsql()
|
||||
@ -179,6 +131,8 @@ namespace Yavsc
|
||||
option.User.RequireUniqueEmail = true;
|
||||
option.Cookies.ApplicationCookie.DataProtectionProvider =
|
||||
new MonoDataProtectionProvider(Configuration["Site:Title"]);
|
||||
option.Cookies.ApplicationCookie.LoginPath = new PathString(Constants.LoginPath.Substring(1));
|
||||
option.Cookies.ApplicationCookie.AccessDeniedPath = new PathString(Constants.AccessDeniedPath.Substring(1));
|
||||
}
|
||||
).AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
.AddTokenProvider<EmailTokenProvider<ApplicationUser>>(Constants.EMailFactor)
|
||||
@ -331,181 +285,21 @@ namespace Yavsc
|
||||
}
|
||||
}
|
||||
|
||||
var googleOptions = 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"
|
||||
};
|
||||
var gvents = new OAuthEvents();
|
||||
|
||||
googleOptions.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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
googleOptions.Scope.Add("https://www.googleapis.com/auth/calendar");
|
||||
|
||||
app.UseIISPlatformHandler(options =>
|
||||
{
|
||||
options.AuthenticationDescriptions.Clear();
|
||||
options.AutomaticAuthentication = true;
|
||||
});
|
||||
|
||||
ConfigureOAuthApp(app);
|
||||
|
||||
ConfigureFileServerApp(app,siteSettings.Value,env);
|
||||
|
||||
app.UseWebSockets();
|
||||
|
||||
app.UseIdentity();
|
||||
|
||||
|
||||
/* app.UseOpenIdConnectServer(options =>
|
||||
{
|
||||
options.Provider = new AuthorizationProvider(loggerFactory,
|
||||
new UserTokenProvider());
|
||||
|
||||
// Register the certificate used to sign the JWT tokens.
|
||||
// options.SigningCredentials.AddCertificate(
|
||||
// assembly: typeof(Startup).GetTypeInfo().Assembly,
|
||||
// resource: "Mvc.Server.Certificate.pfx",
|
||||
// password: "Owin.Security.OpenIdConnect.Server");
|
||||
|
||||
// options.SigningCredentials.AddKey(key);
|
||||
// Note: see AuthorizationController.cs for more
|
||||
// information concerning ApplicationCanDisplayErrors.
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
options.AllowInsecureHttp = true;
|
||||
options.AutomaticChallenge = true;
|
||||
// options.AutomaticAuthenticate=true;
|
||||
|
||||
|
||||
options.AuthorizationEndpointPath = new PathString("/connect/authorize");
|
||||
options.TokenEndpointPath = new PathString("/connect/authorize/accept");
|
||||
options.UseSlidingExpiration = true;
|
||||
options.AllowInsecureHttp = true;
|
||||
options.AuthenticationScheme = "oidc-server"; // was = OpenIdConnectDefaults.AuthenticationScheme || "oidc";
|
||||
options.LogoutEndpointPath = new PathString("/connect/logout");
|
||||
|
||||
// options.ValidationEndpointPath = new PathString("/connect/introspect");
|
||||
}); */
|
||||
|
||||
app.UseCookieAuthentication(options =>
|
||||
{
|
||||
options.AutomaticAuthenticate = true;
|
||||
options.AutomaticChallenge = true;
|
||||
options.AuthenticationScheme = "ServerCookie";
|
||||
options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
|
||||
options.LoginPath = new PathString("/signin");
|
||||
options.LogoutPath = new PathString("/signout");
|
||||
});
|
||||
|
||||
app.UseMiddleware<Yavsc.Auth.GoogleMiddleware>(googleOptions);
|
||||
|
||||
// Facebook
|
||||
app.UseFacebookAuthentication(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.UseOAuthAuthorizationServer(
|
||||
|
||||
options =>
|
||||
{
|
||||
options.AuthorizeEndpointPath = new PathString("/signin");
|
||||
options.TokenEndpointPath = new PathString("/token");
|
||||
options.ApplicationCanDisplayErrors = true;
|
||||
|
||||
#if DEBUG
|
||||
options.AllowInsecureHttp = true;
|
||||
#endif
|
||||
|
||||
options.Provider = new OAuthAuthorizationServerProvider
|
||||
{
|
||||
OnValidateClientRedirectUri = ValidateClientRedirectUri,
|
||||
OnValidateClientAuthentication = ValidateClientAuthentication,
|
||||
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
|
||||
OnGrantClientCredentials = GrantClientCredetails
|
||||
};
|
||||
|
||||
options.AuthorizationCodeProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateAuthenticationCode,
|
||||
OnReceive = ReceiveAuthenticationCode,
|
||||
};
|
||||
|
||||
options.RefreshTokenProvider = new AuthenticationTokenProvider
|
||||
{
|
||||
OnCreate = CreateRefreshToken,
|
||||
OnReceive = ReceiveRefreshToken,
|
||||
};
|
||||
|
||||
options.AutomaticAuthenticate = false;
|
||||
}
|
||||
);
|
||||
|
||||
app.UseRequestLocalization(localizationOptions.Value, (RequestCulture)new RequestCulture((string)"fr"));
|
||||
|
||||
/* Generic OAuth (here GitHub): options.Notifications = new OAuthAuthenticationNotifications
|
||||
{
|
||||
OnGetUserInformationAsync = async context =>
|
||||
{
|
||||
// Get the GitHub user
|
||||
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
|
||||
userRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
|
||||
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
|
||||
HttpResponseMessage userResponse = await context.Backchannel.SendAsync(userRequest, context.HttpContext.RequestAborted);
|
||||
userResponse.EnsureSuccessStatusCode();
|
||||
var text = await userResponse.Content.ReadAsStringAsync();
|
||||
JObject user = JObject.Parse(text);
|
||||
|
||||
var identity = new ClaimsIdentity(
|
||||
context.Options.AuthenticationType,
|
||||
ClaimsIdentity.DefaultNameClaimType,
|
||||
ClaimsIdentity.DefaultRoleClaimType);
|
||||
|
||||
JToken value;
|
||||
var id = user.TryGetValue("id", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(id))
|
||||
{
|
||||
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, id, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var userName = user.TryGetValue("login", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(userName))
|
||||
{
|
||||
identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, userName, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var name = user.TryGetValue("name", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
identity.AddClaim(new Claim("urn:github:name", name, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
var link = user.TryGetValue("url", out value) ? value.ToString() : null;
|
||||
if (!string.IsNullOrEmpty(link))
|
||||
{
|
||||
identity.AddClaim(new Claim("urn:github:url", link, ClaimValueTypes.String, context.Options.AuthenticationType));
|
||||
}
|
||||
|
||||
context.Identity = identity;
|
||||
}
|
||||
}; */
|
||||
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
routes.MapRoute(
|
||||
@ -515,17 +309,7 @@ namespace Yavsc
|
||||
|
||||
app.UseSignalR();
|
||||
}
|
||||
private sealed class SystemWebApplicationDiscriminator : IApplicationDiscriminator
|
||||
{
|
||||
private readonly Lazy<string> _lazyDiscriminator = new Lazy<string>(GetAppDiscriminatorCore);
|
||||
|
||||
public string Discriminator => _lazyDiscriminator.Value;
|
||||
|
||||
private static string GetAppDiscriminatorCore()
|
||||
{
|
||||
return HttpRuntime.AppDomainAppId;
|
||||
}
|
||||
}
|
||||
|
||||
// Entry point for the application.
|
||||
public static void Main(string[] args) => Microsoft.AspNet.Hosting.WebApplication.Run<Startup>(args);
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
|
||||
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Yavsc
|
||||
{
|
||||
public class AuthorisationView {
|
||||
public OpenIdConnectMessage Message { get; set; }
|
||||
public Application Application { get; set; }
|
||||
public IEnumerable<string> Scopes { get; set; }
|
||||
public string RedirectUrl { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -1,20 +1,18 @@
|
||||
@using System.Collections.Generic
|
||||
@using Microsoft.AspNet.Http
|
||||
@using Microsoft.AspNet.Http.Authentication
|
||||
@model LoginViewModel
|
||||
@inject SignInManager<ApplicationUser> SignInManager
|
||||
|
||||
@using Microsoft.AspNet.Http.Authentication
|
||||
@using Yavsc.ViewModels.Account
|
||||
@model LoginViewModel
|
||||
@{
|
||||
ViewData["Title"] = SR["Log in"];
|
||||
}
|
||||
|
||||
<h2>@ViewData["Title"]</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<section>
|
||||
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
|
||||
<h4>@SR["Use a local account to log in."]</h4>
|
||||
<hr />
|
||||
<div class="jumbotron">
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
<hr/>
|
||||
|
||||
<h2 class="lead text-left">@SR["Use a local account to log in"]</h2>
|
||||
<form action="@Constants.LoginPath" method="post" class="form-horizontal" role="form">
|
||||
|
||||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label for="UserName" class="col-md-2 control-label">@SR["UserName"]</label>
|
||||
@ -40,25 +38,24 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-offset-2 col-md-10">
|
||||
<button type="submit" class="btn btn-default">@SR["Login"]</button>
|
||||
<button type="submit" class="btn btn-lg btn-success">@SR["Login"]</button>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<a asp-action="Register">@SR["Register as a new user?"]</a>
|
||||
<a asp-action="Register" asp-controller="Account">@SR["Register as a new user"]?</a>
|
||||
</p>
|
||||
<p>
|
||||
<a asp-action="ForgotPassword">@SR["Forgot your password?"]</a>
|
||||
<a asp-action="ForgotPassword" asp-controller="Account">@SR["Forgot your password"]?</a>
|
||||
</p>
|
||||
<input type="hidden" name="Provider" value="LOCAL" />
|
||||
<input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
|
||||
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<section>
|
||||
<h4>@SR["Use another service to log in."]</h4>
|
||||
<hr />
|
||||
@{
|
||||
var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
|
||||
if (loginProviders.Count == 0)
|
||||
|
||||
<hr/>
|
||||
<h2 class="lead text-left">@SR["Use another service to log in"]:</h2>
|
||||
@if (Model.ExternalProviders?.Count() == 0)
|
||||
{
|
||||
<div>
|
||||
<p>
|
||||
@ -69,22 +66,13 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
|
||||
<div>
|
||||
<p>
|
||||
@foreach (var provider in loginProviders)
|
||||
{
|
||||
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
@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">@SR["Connect using"] @description.DisplayName</button>
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
}
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
||||
|
32
Yavsc/Views/OAuth/Authorize.cshtml
Normal file
32
Yavsc/Views/OAuth/Authorize.cshtml
Normal file
@ -0,0 +1,32 @@
|
||||
@using Microsoft.AspNet.Http.Authentication
|
||||
@using Microsoft.AspNet.WebUtilities
|
||||
@using System.Security.Claims
|
||||
@{
|
||||
AuthenticationManager authentication = Context.Authentication;
|
||||
ClaimsPrincipal principal = authentication.AuthenticateAsync(Constants.ApplicationAuthenticationSheme).Result;
|
||||
string[] scopes = QueryHelpers.ParseQuery(Context.Request.QueryString.Value)["scope"];
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Authorize</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Authorization Server</h1>
|
||||
<h2>OAuth2 Authorize</h2>
|
||||
<form method="POST">
|
||||
<p>Hello, @principal.Identity.Name</p>
|
||||
<p>A third party application want to do the following on your behalf:</p>
|
||||
<ul>
|
||||
@foreach (var scope in scopes)
|
||||
{
|
||||
<li>@scope</li>
|
||||
}
|
||||
</ul>
|
||||
<p>
|
||||
<input type="submit" name="submit.Grant" value="Grant" />
|
||||
<input type="submit" name="submit.Login" value="Sign in as different user" />
|
||||
</p>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
20
Yavsc/Views/OAuth/AuthorizeError.cshtml
Normal file
20
Yavsc/Views/OAuth/AuthorizeError.cshtml
Normal file
@ -0,0 +1,20 @@
|
||||
@using Microsoft.AspNet.Http
|
||||
@using System
|
||||
@using System.Security.Claims
|
||||
@{
|
||||
var error = Context.Items["oauth.Error"];
|
||||
var errorDescription = Context.Items["oauth.ErrorDescription"];
|
||||
var errorUri = Context.Items["oauth.ErrorUri"];
|
||||
}
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Authorize Error</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Katana.Sandbox.WebServer</h1>
|
||||
<h2>OAuth2 Authorize Error</h2>
|
||||
<p>Error: @error</p>
|
||||
<p>@errorDescription</p>
|
||||
</body>
|
||||
</html>
|
@ -1,22 +1,22 @@
|
||||
@using AspNet.Security.OpenIdConnect.Extensions
|
||||
@using Microsoft.IdentityModel.Protocols.OpenIdConnect
|
||||
|
||||
|
||||
|
||||
@model AuthorisationView
|
||||
|
||||
<div class="jumbotron">
|
||||
<h1>Authorization</h1>
|
||||
<h1>Authorization @Application?.DisplayName</h1>
|
||||
|
||||
<p>@Model.Message</p>
|
||||
|
||||
<p class="lead text-left">Do you wanna grant <strong>@Model.Application.DisplayName</strong> an access to your resources? (scopes requested: @Model.Message.Scope)</p>
|
||||
|
||||
<form enctype="application/x-www-form-urlencoded" method="post">
|
||||
@Html.AntiForgeryToken()
|
||||
|
||||
@foreach (var parameter in Model.Message.Parameters) {
|
||||
<input type="hidden" name="@parameter.Key" value="@parameter.Value" />
|
||||
@foreach (var scope in Model.Scopes) {
|
||||
<li>@scope</li>
|
||||
}
|
||||
<input formaction="/connect/authorize/accept" class="btn btn-lg btn-success" name="Authorize" type="submit" value="Yeah, sure" />
|
||||
<input formaction="/api/token/get" class="btn btn-lg btn-success" name="Authorize" type="submit" value="hum" />
|
||||
<input formaction="/connect/authorize/deny" class="btn btn-lg btn-danger" name="Deny" type="submit" value="Hell, no" />
|
||||
</form>
|
||||
@Html.Hidden("ReturnUrl")
|
||||
<input formaction="/oauth/accept" class="btn btn-lg btn-success" name="Authorize" type="submit" value="Yeah, sure" />
|
||||
<input formaction="/oauth/deny" class="btn btn-lg btn-danger" name="Deny" type="submit" value="Hell, no" />
|
||||
<input formaction="/oauth/deny" class="btn btn-lg btn-success" name="Submit.Login" type="submit" value="Login using another account" />
|
||||
</form>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@
|
||||
<hr/>
|
||||
|
||||
<h2 class="lead text-left">@SR["Use a local account to log in"]</h2>
|
||||
<form action="/login" method="post" class="form-horizontal" role="form">
|
||||
<form action="@Constants.LoginPath" method="post" class="form-horizontal" role="form">
|
||||
|
||||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
@ -67,7 +67,7 @@
|
||||
else
|
||||
{
|
||||
@foreach (var description in Model.ExternalProviders) {
|
||||
<form action="/signin" method="post">
|
||||
<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">@SR["Connect using"] @description.DisplayName</button>
|
||||
|
@ -48,7 +48,7 @@ gulp.task("min:css", function () {
|
||||
|
||||
gulp.task("min", ["min:js", "min:css"]);
|
||||
|
||||
gulp.task('watch', shell.task(['MONO_OPTIONS=--debug ASPNET_ENV=Development dnx-watch web --configuration=Debug']))
|
||||
gulp.task('watch', shell.task(['ASPNET_ENV=Development dnx-watch web --configuration=Debug']))
|
||||
|
||||
gulp.task('build', shell.task(['dnu build --configuration=Debug']))
|
||||
gulp.task('publish', shell.task(['dnu publish -o ../build']))
|
||||
|
@ -88,18 +88,15 @@
|
||||
"Microsoft.Extensions.Globalization.CultureInfoCache": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.Localization": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.Localization.Abstractions": "1.0.0-rc1-final",
|
||||
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
|
||||
"Microsoft.Framework.DependencyInjection": "1.0.0-beta8",
|
||||
|
||||
"Microsoft.Extensions.CodeGeneration": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc1-final",
|
||||
"Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
|
||||
"Microsoft.Framework.ConfigurationModel.Json": "1.0.0-beta4",
|
||||
"Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta8",
|
||||
"Microsoft.Framework.Configuration.Binder": "1.0.0-beta8",
|
||||
"Microsoft.Framework.Configuration.Json": "1.0.0-beta8",
|
||||
"Microsoft.AspNet.Session": "1.0.0-rc1-final",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-beta-23516",
|
||||
"Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta8",
|
||||
"Microsoft.Framework.Configuration.Json": "1.0.0-beta8",
|
||||
"Microsoft.Framework.DependencyInjection.Abstractions": "1.0.0-beta8",
|
||||
"Microsoft.Framework.Configuration.Binder": "1.0.0-beta8",
|
||||
"Microsoft.AspNet.Web.Optimization": "1.1.3",
|
||||
"Microsoft.Extensions.WebEncoders.Core": "1.0.0-rc1-final",
|
||||
"Microsoft.AspNetCore.Authentication.OAuth": "0.0.1-alpha",
|
||||
|
File diff suppressed because it is too large
Load Diff
2
external/oauth-aspnet
vendored
2
external/oauth-aspnet
vendored
Submodule external/oauth-aspnet updated: 3ce8e24903...1fdf3cb799
@ -67,7 +67,7 @@ namespace testOauthClient
|
||||
app.UseOAuthAuthentication(
|
||||
options => {
|
||||
options.AuthenticationScheme="yavsc";
|
||||
options.AuthorizationEndpoint="http://dev.pschneider.fr/signin";
|
||||
options.AuthorizationEndpoint="http://dev.pschneider.fr/authorize";
|
||||
options.TokenEndpoint="http://dev.pschneider.fr/token";
|
||||
options.AutomaticAuthenticate=true;
|
||||
options.AutomaticChallenge=true;
|
||||
|
Reference in New Issue
Block a user