Aspnet Identity (OWIN) - Front end authentication without impacting "backoffice"
Hi
This is my first post in this forum. Please excuse me if this is already asked by some one and answered.
I want to have "custom authentication" for my website (just the front end) , I do not want to change the backend. The "front end" requires valid credentials (this is validated against an api) and if the "credentials" are valid, the required information such as user name and other fields is stored to cookie (aspnet identity).
Code snippet: (The namespace XYZ is not my real namespace. For the purpose of this post, I replace my namespace with XYZ)
Web.config:
<add key="owin:appStartup" value="XYZ.Startup" />
Startup.cs
[assembly: OwinStartup(typeof(XYZ.Startup))]
namespace XYZ
{
public partial class Startup : UmbracoDefaultOwinStartup
{
public override void Configuration(IAppBuilder app)
{
base.Configuration(app);
ConfigureAuth(app);
}
}
}
Startup.Auth.cs:
namespace XYZ
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
var Identity = new ClaimsIdentity(new[] {
new Claim(ClaimTypes.NameIdentifier,"Id"),
new Claim(ClaimTypes.Name,"Name"),
new Claim("ClaimType","Value")
}, DefaultAuthenticationTypes.ApplicationCookie);
var ctx = Request.GetOwinContext();
var authManager = ctx.Authentication;
The front end is working great. However it has an impact on the "Back office". After I enter the user name and password, the back office is trying to redirect to "signin" which is supposed to be used by front end only.
Could you please advise what is wrong. If I remove "ConfigureAuth" the back office is working fine but not the "front end".
(I will try to create an empty project and upload the code to GITHUB)
We faced similar issues when using a ASP.NET identity with a custom store. Luckily we could solve it.
This is how my owin startup looks.
public class OwinStartup : UmbracoDefaultOwinStartup
{
/// <summary>
/// Configures services to be created in the OWIN context (CreatePerOwinContext)
/// </summary>
/// <param name="app"></param>
protected override void ConfigureServices(IAppBuilder app)
{
base.ConfigureServices(app);
}
/// <summary>Configures middleware to be used (i.e. app.Use...)</summary>
/// <param name="app"></param>
protected override void ConfigureMiddleware(IAppBuilder app)
{
base.ConfigureMiddleware(app);
// TODO set correct login path
app.UseCookieAuthentication(
new FrontEndCookieAuthenticationOptions
{
LoginPath = new PathString("/nl/login"),
//Provider = new CookieAuthenticationProvider
//{
// // Enables the application to validate the security stamp when the user logs in.
// // This is a security feature which is used when you change a password or add an external login to your account.
// OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<OypoUserManager, OypoUser>(
// validateInterval: TimeSpan.FromMinutes(30),
// regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
//}
});
}
}
This is the code for FrontEndCookieAuthenticationOptions.
internal class FrontEndCookieAuthenticationOptions : CookieAuthenticationOptions
{
public FrontEndCookieAuthenticationOptions()
{
CookieManager = new FrontEndCookieManager();
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie;
}
}
And this is the code for the FrontEndCookieManager
internal class FrontEndCookieManager : ChunkingCookieManager, ICookieManager
{
/// <summary>
/// Explicitly implement this so that we filter the request
/// </summary>
/// <param name="context"></param>
/// <param name="key"></param>
/// <returns></returns>
string ICookieManager.GetRequestCookie(IOwinContext context, string key)
{
if (UmbracoContext.Current == null || IsClientSideRequest(context.Request.Uri))
{
return null;
}
var authForBackOffice = ShouldAuthForBackOfficeRequest(context);
return authForBackOffice
// Don't auth request since this is for the back office, don't return a cookie
? null
// Return the default implementation
: base.GetRequestCookie(context, key);
}
private static bool IsClientSideRequest(Uri url)
{
var ext = Path.GetExtension(url.LocalPath);
if (ext.IsNullOrWhiteSpace())
{
return false;
}
var toInclude = new[] { ".aspx", ".ashx", ".asmx", ".axd", ".svc" };
return toInclude.Any(ext.InvariantEquals) == false;
}
private static bool IsBackOfficeRequest(IOwinRequest request)
{
return (bool)typeof(UriExtensions).CallStaticMethod("IsBackOfficeRequest", request.Uri, HttpRuntime.AppDomainAppVirtualPath);
}
private static bool IsInstallerRequest(IOwinRequest request)
{
return (bool)typeof(UriExtensions).CallStaticMethod("IsInstallerRequest", request.Uri);
}
/// <summary>
/// Determines if the request should be authenticated for the back office
/// </summary>
/// <param name="ctx"></param>
/// <returns></returns>
/// <remarks>
/// We auth the request when:
/// * it is a back office request
/// * it is an installer request
/// * it is a preview request
/// </remarks>
private bool ShouldAuthForBackOfficeRequest(IOwinContext ctx)
{
var request = ctx.Request;
if (//check back office
IsBackOfficeRequest(request)
//check installer
|| IsInstallerRequest(request))
{
return true;
}
return false;
}
}
Hi Dave, Another quick query please. Did you install the Umbraco Identity package and customize the code (or) is it just the normal way without installing Umbraco Identity package ?
Thanks so much. I followed similar approach, didn't install Umbraco identity package and I have this working as I expect. The backend authentication still works as-is, I have my own custom authentication and authorization for front end.
We have a similar setup too, but have found that it causes preview of an unpublished page to stop working.
This appears to be because previewing an unpublished page requires you to have a User.Identity that is an UmbracoBackOfficeIdentity and when using this that is no longer true.
Has anybody encountered this? Solved this? Or has any idea how we might do?
Following the instructions in the description and this post I managed to get front end and back office authentication working without impacting each other with preview also working.
Could you please both post your solutions? I've been banging my head against the wall for the last couple of weeks trying to get through my authentication woes.
You both say you have solutions similar's to Dave's, so I'm mainly curious what the differences are. Did you also follow the Config Updates recommended in https://github.com/Shazwazza/UmbracoIdentity ?
My set up is Umbraco 7.4.3 in an Azure Web App, and I'm trying to add Azure Authorization / Authentication (aka Easy Auth) using ActiveDirectory.
I've tried the solution posted by Dave above (modified slightly to work with Easy Auth) and it mostly works, but I'm running into issues with:
Dumb question, but what does ApplicationContext refer to here? Not super well versed in ASP.Net and working to tweak the UmbracoIdentity stuff to allow Okta to login front-end members, but prevent BackOffice from being affected.
It's been a long time since I worked on this and my memory on it is hazy at best, but I'll give this a go.
ApplicationContext is just an object that contains application wide information (such as how to authenticate users). From memory this was just an object that was available on an inherited property within the OwinStartup class. I believed it was an ASP.Net thing, but a quick Google is struggling to back that up with any documentation or evidence, so maybe I'm mistaken. I'm afraid that's really all I've got. Unfortunately, I no longer have access to the code base in question, so I can't confirm any more than what I remember.
I'm trying to do something similar, but cannot quite wrap my head around it. I have this existing Umbraco setup where I use the default forms authentication for logging into the back-office.
How ever, I would like to protect some of the front-end controller actions via AuthorizeAttribute, requiring the users who try to execute these to logon via Azure AD B2C.
I have an existing OWIN implementation for Azure AD B2C in a non-Umbraco web application using Microsoft.Owin.Security.OpenIdConnect. How to integrate this setup with this workaround?
We had an outside consultant (FYIN.com) assist with getting our intranet to use Okta for front-end logins, though we didn't quite get it working with back-end logins, hence the commented-out code at the end. Had to also add Okta's Authorization Services to our Okta subscription in order to set up some of the tokens for that approach. Feel free to peruse our MyOwinStartup.cs at GitHub.
Aspnet Identity (OWIN) - Front end authentication without impacting "backoffice"
Hi
This is my first post in this forum. Please excuse me if this is already asked by some one and answered.
I want to have "custom authentication" for my website (just the front end) , I do not want to change the backend. The "front end" requires valid credentials (this is validated against an api) and if the "credentials" are valid, the required information such as user name and other fields is stored to cookie (aspnet identity).
Code snippet: (The namespace XYZ is not my real namespace. For the purpose of this post, I replace my namespace with XYZ)
Web.config:
Startup.cs
[assembly: OwinStartup(typeof(XYZ.Startup))] namespace XYZ { public partial class Startup : UmbracoDefaultOwinStartup { public override void Configuration(IAppBuilder app) { base.Configuration(app); ConfigureAuth(app); } } }
Startup.Auth.cs:
namespace XYZ { public partial class Startup { public void ConfigureAuth(IAppBuilder app) {
}
Source code of "SignIn":
var Identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier,"Id"), new Claim(ClaimTypes.Name,"Name"), new Claim("ClaimType","Value") }, DefaultAuthenticationTypes.ApplicationCookie);
authManager.SignIn(new AuthenticationProperties() { AllowRefresh = true, IsPersistent = true, ExpiresUtc=DateTime.UtcNow.AddHours(1) }, Identity);
The front end is working great. However it has an impact on the "Back office". After I enter the user name and password, the back office is trying to redirect to "signin" which is supposed to be used by front end only.
Could you please advise what is wrong. If I remove "ConfigureAuth" the back office is working fine but not the "front end".
(I will try to create an empty project and upload the code to GITHUB)
Thanks Bharati.
Hi Bharati
We faced similar issues when using a ASP.NET identity with a custom store. Luckily we could solve it.
This is how my owin startup looks.
This is the code for FrontEndCookieAuthenticationOptions.
And this is the code for the FrontEndCookieManager
This solved our issues. We "borrowed" this code from https://github.com/Shazwazza/UmbracoIdentity
Dave
Hi Dave,
What namespace does CallStaticMethod() belong to?
I am getting a build error, that I am missing a namespace.
Any help would be greatly appreciated.
Thanks
Craig
Did you ever get a reply to what namespace "CallStaticMethod()" is from? I'm getting the same build error.
Thanks so much. (I was on holiday hence couldn't respond)
Hi Dave, Another quick query please. Did you install the Umbraco Identity package and customize the code (or) is it just the normal way without installing Umbraco Identity package ?
Hi Bhatari,
I did not install the Umbraco Identity package because this is for Umbraco members. We needed to implement our own custom store.
Dave
Thanks so much. I followed similar approach, didn't install Umbraco identity package and I have this working as I expect. The backend authentication still works as-is, I have my own custom authentication and authorization for front end.
:-)
We have a similar setup too, but have found that it causes preview of an unpublished page to stop working.
This appears to be because previewing an unpublished page requires you to have a User.Identity that is an UmbracoBackOfficeIdentity and when using this that is no longer true.
Has anybody encountered this? Solved this? Or has any idea how we might do?
Hi Mark, I just tried this and you are right I can't see preview of an unpublished page.
I get "Page not found" page when previewing a saved page.
I am not sure if there is 'defect log' so we can post it there ?
Hi Bharati,
I went to add a defect to Umbraco's issue tracker the same day I posted and ended up finding this issue that discusses this problem:
http://issues.umbraco.org/issue/U4-4219
Following the instructions in the description and this post I managed to get front end and back office authentication working without impacting each other with preview also working.
Mark
Hi Bharati and Mark,
Could you please both post your solutions? I've been banging my head against the wall for the last couple of weeks trying to get through my authentication woes.
You both say you have solutions similar's to Dave's, so I'm mainly curious what the differences are. Did you also follow the Config Updates recommended in https://github.com/Shazwazza/UmbracoIdentity ?
My set up is Umbraco 7.4.3 in an Azure Web App, and I'm trying to add Azure Authorization / Authentication (aka Easy Auth) using ActiveDirectory.
I've tried the solution posted by Dave above (modified slightly to work with Easy Auth) and it mostly works, but I'm running into issues with:
Any help would be appreciated.
Thanks!
Hi Dmitry,
It's been a while, but I think our solution was as above, but with this ConfigureMiddleware method instead
Hope this helps,
Mark
Dumb question, but what does ApplicationContext refer to here? Not super well versed in ASP.Net and working to tweak the UmbracoIdentity stuff to allow Okta to login front-end members, but prevent BackOffice from being affected.
It's been a long time since I worked on this and my memory on it is hazy at best, but I'll give this a go.
ApplicationContext is just an object that contains application wide information (such as how to authenticate users). From memory this was just an object that was available on an inherited property within the OwinStartup class. I believed it was an ASP.Net thing, but a quick Google is struggling to back that up with any documentation or evidence, so maybe I'm mistaken. I'm afraid that's really all I've got. Unfortunately, I no longer have access to the code base in question, so I can't confirm any more than what I remember.
Hope this helps
I'm trying to do something similar, but cannot quite wrap my head around it. I have this existing Umbraco setup where I use the default forms authentication for logging into the back-office.
How ever, I would like to protect some of the front-end controller actions via
AuthorizeAttribute
, requiring the users who try to execute these to logon via Azure AD B2C.I have an existing OWIN implementation for Azure AD B2C in a non-Umbraco web application using
Microsoft.Owin.Security.OpenIdConnect
. How to integrate this setup with this workaround?Hi Bharati,
I have Integrated this Plugin in my solution,I have a query regarding on how can i switch to the custom Members table with is not in umbraco.
i want to switch to custom database with all integration as it is.
is there any way to fix this.
Thanks, Pradeep
Hi Bharati,
I have Integrated this Plugin in my solution,I have a query regarding on how can i switch to the custom Members table which is not in umbraco.
i want to switch to custom database with all integration as it is.
is there any way to fix this.
Thanks, Pradeep
Eric, did you get this to work with UmbracoIdentity , or did you end up going a different route?
We had an outside consultant (FYIN.com) assist with getting our intranet to use Okta for front-end logins, though we didn't quite get it working with back-end logins, hence the commented-out code at the end. Had to also add Okta's Authorization Services to our Okta subscription in order to set up some of the tokens for that approach. Feel free to peruse our MyOwinStartup.cs at GitHub.
is working on a reply...