Has anyone built a full OAuth Authorization Server?
I am attempting to do so, but for some reason login doesn't redirect to the authorization after the OwinContext.Authentication.SignIn code, and I am at a dead end on where to proceed.
I built a identity server based on this post and works well. https://our.umbraco.org/forum/developers/api-questions/74807-securing-a-custom-api-controller-with-oauth-plus-members
And I am attempting to extend it to a full authorization server
I added the following to my UmbracoAuthTokenServerExtensions
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//generally you wouldn't allow this unless on SSL!
AllowInsecureHttp = true,
ApplicationCanDisplayErrors = true,
TokenEndpointPath = new PathString("/oauth/token"),
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
AuthorizeEndpointPath = new PathString("/oauth/authorize"),
Provider = new MembersAuthServerProvider(membersAuthServerProviderOptions)
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
},
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthorisationCode,
OnReceive = ReceiveAuthorisationCode,
},
AccessTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAccessToken,
OnReceive = ReceiveAccessToken,
},
// Refresh token provider which creates and receives referesh token
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
}
// AccessTokenFormat = new CustomJwtFormat(HttpContext.Current.Request.UserHostName)
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
//app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ApplicationCookie);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
LoginPath = new PathString(AuthPaths.LoginPath),
LogoutPath = new PathString(AuthPaths.LogoutPath),
});
My Login controller
[HttpPost]
public async Task<ActionResult> LoginAuth(LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.Email, model.Password);
if (user != null)
{
await SignInAsync(user, true);
return RedirectToCurrentUmbracoPage();
}
ModelState.AddModelError("", "Invalid username/password");
}
return CurrentUmbracoPage();
}
private UmbracoMembersUserManager<UmbracoApplicationMember> _userManager;
public UmbracoMembersUserManager<UmbracoApplicationMember> UserManager
{
get
{
return _userManager ?? (_userManager = OwinContext
.GetUserManager<UmbracoMembersUserManager<UmbracoApplicationMember>>());
}
}
protected IOwinContext OwinContext
{
get { return Request.GetOwinContext(); }
}
private async Task SignInAsync(UmbracoApplicationMember member, bool isPersistent)
{
OwinContext.Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var userIdentity = await UserManager.CreateIdentityAsync(member, DefaultAuthenticationTypes.ApplicationCookie);
OwinContext.Authentication.SignIn(
new AuthenticationProperties { IsPersistent = isPersistent },
userIdentity);
}
And my Authorisation Controller
public ActionResult Authorize()
{
if (Response.StatusCode != 200)
{
// TODO tidy this view and log.
log.Warn(string.Concat("Authorize Error, Response Code:", Response.StatusCode ));
return View("AuthorizeError");
}
// Get auth context and see if we have a ticket.
var authentication = HttpContext.GetOwinContext().Authentication;
var ticket = authentication.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie).Result;
var identity = ticket != null ? ticket.Identity : null;
if (identity == null)
{
// No ticket - so challenge (results in redirect to /account/login)
authentication.Challenge("Application");
log.Info("Challenging Authorizaton");
return new HttpUnauthorizedResult();
}
var scopes = (Request.QueryString.Get("scope") ?? "").Split(' ');
var autoGrant = true; // Not currently supporting the "grant" screen for any clients - implicit.
var submitGrant = Request.HttpMethod == "POST" && (!string.IsNullOrEmpty(Request.Form.Get("submit.Grant")));
if (submitGrant || autoGrant)
{
identity = new ClaimsIdentity(identity.Claims, "Bearer", identity.NameClaimType, identity.RoleClaimType);
foreach (var scope in scopes)
{
identity.AddClaim(new Claim("urn:oauth:scope", scope));
}
authentication.SignIn(identity);
log.Info("Grant Added");
}
else if (Request.HttpMethod == "POST" && (!string.IsNullOrEmpty(Request.Form.Get("submit.Login"))))
{
authentication.SignOut("Application");
authentication.Challenge("Application");
return new HttpUnauthorizedResult();
}
return View();
}