Created
October 1, 2015 12:12
-
-
Save ilmax/71fc46d7fc35ef2f8fc8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Authorize, HttpPost, Route("~/connect/authorize/accept"), ValidateAntiForgeryToken] | |
public async Task<ActionResult> Accept(CancellationToken cancellationToken) | |
{ | |
// Extract the authorization request from the cache, the query string or the request form. | |
var request = OwinContext.GetOpenIdConnectRequest(); | |
if (request == null) | |
{ | |
return View("Error", new OpenIdConnectMessage | |
{ | |
Error = "invalid_request", | |
ErrorDescription = "An internal error has occurred" | |
}); | |
} | |
// Create a new ClaimsIdentity containing the claims that | |
// will be used to create an id_token, a token or a code. | |
var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType); | |
foreach (var claim in OwinContext.Authentication.User.Claims) | |
{ | |
// Allow ClaimTypes.Name to be added in the id_token. | |
// ClaimTypes.NameIdentifier is automatically added, even if its | |
// destination is not defined or doesn't include "id_token". | |
// The other claims won't be visible for the client application. | |
if (claim.Type == ClaimTypes.Name) | |
{ | |
claim.WithDestination("id_token") | |
.WithDestination("token"); | |
} | |
identity.AddClaim(claim); | |
} | |
// Note: Owin.Security.OpenIdConnect.Server automatically ensures an application | |
// corresponds to the client_id specified in the authorization request using | |
// IOpenIdConnectServerProvider.ValidateClientRedirectUri (see AuthorizationProvider.cs). | |
// In theory, this null check is thus not strictly necessary. That said, a race condition | |
// and a null reference exception could appear here if you manually removed the application | |
// details from the database after the initial check made by Owin.Security.OpenIdConnect.Server. | |
var application = await GetApplicationAsync(request.ClientId, CancellationToken.None); | |
if (application == null) | |
{ | |
return View("Error", new OpenIdConnectMessage | |
{ | |
Error = "invalid_client", | |
ErrorDescription = "Details concerning the calling client application cannot be found in the database" | |
}); | |
} | |
// Create a new ClaimsIdentity containing the claims associated with the application. | |
// Note: setting identity.Actor is not mandatory but can be useful to access | |
// the whole delegation chain from the resource server (see ResourceController.cs). | |
identity.Actor = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType); | |
identity.Actor.AddClaim(ClaimTypes.NameIdentifier, application.ApplicationID); | |
identity.Actor.AddClaim(ClaimTypes.Name, application.DisplayName, destination: "id_token token"); | |
// This call will instruct Owin.Security.OpenIdConnect.Server to serialize | |
// the specified identity to build appropriate tokens (id_token and token). | |
// Note: you should always make sure the identities you return contain either | |
// a 'sub' or a 'ClaimTypes.NameIdentifier' claim. In this case, the returned | |
// identities always contain the name identifier returned by the external provider. | |
OwinContext.Authentication.SignIn(identity); | |
return new HttpStatusCodeResult(200); | |
} | |
[Authorize, HttpPost, Route("~/connect/authorize/deny"), ValidateAntiForgeryToken] | |
public ActionResult Deny(CancellationToken cancellationToken) | |
{ | |
// Extract the authorization request from the cache, the query string or the request form. | |
var request = OwinContext.GetOpenIdConnectRequest(); | |
if (request == null) | |
{ | |
return View("Error", new OpenIdConnectMessage | |
{ | |
Error = "invalid_request", | |
ErrorDescription = "An internal error has occurred" | |
}); | |
} | |
// Notify Owin.Security.OpenIdConnect.Server that the authorization grant has been denied. | |
// Note: OpenIdConnectServerHandler will automatically take care of redirecting | |
// the user agent to the client application using the appropriate response_mode. | |
OwinContext.SetOpenIdConnectResponse(new OpenIdConnectMessage | |
{ | |
Error = "access_denied", | |
ErrorDescription = "The authorization grant has been denied by the resource owner", | |
RedirectUri = request.RedirectUri, | |
State = request.State | |
}); | |
return new HttpStatusCodeResult(200); | |
} | |
[HttpPost, Route("~/connect/authorize/login"), ValidateAntiForgeryToken] | |
public async Task<ActionResult> PasswordLogin(CancellationToken cancellationToken, LoginModel login) | |
{ | |
Debug.Assert(!User.Identity.IsAuthenticated); | |
// Extract the authorization request from the cache, the query string or the request form. | |
var request = OwinContext.GetOpenIdConnectRequest(); | |
if (request == null) | |
{ | |
return View("Error", new OpenIdConnectMessage | |
{ | |
Error = "invalid_request", | |
ErrorDescription = "An internal error has occurred" | |
}); | |
} | |
// Note: Owin.Security.OpenIdConnect.Server automatically ensures an application | |
// corresponds to the client_id specified in the authorization request using | |
// IOpenIdConnectServerProvider.ValidateClientRedirectUri (see AuthorizationProvider.cs). | |
// In theory, this null check is thus not strictly necessary. That said, a race condition | |
// and a null reference exception could appear here if you manually removed the application | |
// details from the database after the initial check made by Owin.Security.OpenIdConnect.Server. | |
var application = await GetApplicationAsync(request.ClientId, cancellationToken); | |
if (application == null) | |
{ | |
return View("Error", new OpenIdConnectMessage | |
{ | |
Error = "invalid_client", | |
ErrorDescription = "Details concerning the calling client application cannot be found in the database" | |
}); | |
} | |
// Implement your credential validation logic and create an identity with all necessary claims | |
// NOTE! you MUST add at least the "sub" or ClaimTypes.NameIdentifier claim to the created identity | |
if (login.UserName == login.Password) | |
{ | |
var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationType); | |
identity.AddClaim(new Claim(ClaimTypes.Name, login.UserName).WithDestination("id_token token")); | |
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "1").WithDestination("id_token token")); | |
if (application.RequireUserConsent) | |
{ | |
// Note this is because we generate an AntiForgeryToken in both Views (Authorize & Login) so we should consume (remove) | |
// the token used by Login view. | |
request.Parameters.Remove("__RequestVerificationToken"); | |
// Note: in a real world application, you'd probably prefer creating a specific view model. | |
return View("Authorize", Tuple.Create(request, application)); | |
} | |
// Where should i put this line ? | |
OwinContext.Authentication.SignIn(identity); | |
return new HttpStatusCodeResult(200); | |
} | |
return View("Login", new LoginViewModel(login.Unique_Id, "Wrong password")); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@model Mvc.Server.Models.LoginViewModel | |
@{ | |
ViewBag.Title = "Login"; | |
} | |
<div class="jumbotron"> | |
<h2>Login</h2> | |
<h1>Authorization Server</h1> | |
@if (!string.IsNullOrEmpty(Model.Error)) | |
{ | |
<h1 style="color:red">@Model.Error</h1> | |
} | |
<form action="/connect/authorize/login" enctype="application/x-www-form-urlencoded" method="post"> | |
@Html.AntiForgeryToken() | |
<div class="form-horizontal"> | |
<h4>Forms Login</h4> | |
<hr /> | |
<input type="hidden" name="unique_id" value="@Model.UniqueId" /> | |
<div class="form-group"> | |
<div class="col-md-10"> | |
<label for="UserName">User name: </label> | |
<input type="text" id="UserName" name="username" /> | |
</div> | |
</div> | |
<div class="form-group"> | |
<div class="col-md-10"> | |
<label for="Password">Password: </label> | |
<input type="password" id="Password" name="password" /> | |
</div> | |
</div> | |
<div class="form-group"> | |
<div class="col-md-10"> | |
<label for="RememberMe">Remember Me</label> | |
<input type="checkbox" id="RememberMe" name="isPersistent" /> | |
</div> | |
</div> | |
<div class="form-group"> | |
<div class="col-md-offset-2 col-md-10"> | |
<input type="submit" value="Sign In" class="btn btn-default" /> | |
</div> | |
</div> | |
</div> | |
</form> | |
</div> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment