How can I add [Authorize] to all front-end pages [via controller maybe]
Odd question, but I'm trying to secure an Umbraco 8.1.4 intranet by using Okta to auto-login staff with their Windows credentials (using essentially these steps).
I've modified a MyOwinStartup.cs to include the Okta code, plus added the line "GlobalFilters.Filters.Add(new AuthorizeAttribute())", which forces all controllers to require authorization. This approach works fine for the front end, but BackOffice users find that after login they can't do anything else (404 errors etc).
Short of implementing the full UmbracoIdentity approach (trying to avoid the whole Members approach, don't really need that level of login control), is there a way to maybe include a surface controller on every page to which we could prepend the [Authorize] keyword? I'd then remove the GlobalFilters code from MyOwinStartup.
Or if there's a better (but still sorta easy) approach, would love to hear what others recommend.
I'm not sure if this is what you need for what you are trying to achieve but you can replace the default RenderMvcController that Umbraco uses with your own implementation... Eg create a new controller; inherit RenderMvcController and set it as the default during composing...
Still feel like I'm so close yet so far. Okta works for auto-logging in people to front-end pages (not as Members, strictly as Windows-authenticated users), but the BackOffice throws a bunch of errors after login:
Per Marc's suggestion, I replaced the default RenderMvcController to include the [Authorize] parameter, see code below from my App_Start/SetDefaultMvcControllerComposer.cs. This does seem to correctly trigger Okta to log users in when they first hit any front-end page.
Web.config has these lines which pertain to Okta login:
And lastly, App_Start/MyOwinStartup.cs which has both recently-added Okta code, and some earlier code for logging in Backoffice users:
If it's actually better/easier to incorporate Okta login into the UmbracoIdentity code example, we're happy to go that route also, it just seemed like more than we needed since we're not really using the Members section of Umbraco in this intranet, and only are needing Windows Authentication (and can't just set the overall app in IIS to use Windows Authentication because of some mobile and other out-of-office users).
Any updates around this? I seem to have the same problem in reverse with the Google Authenticator, I've managed to get it working for the back office but not the front end. Although I only moved to using the Google Auth because I had trouble getting Okta to work so if you've managed that then I'd really appreciate any advice?
We ended up contracting with FYIN to finish our Okta integration. Works great for front-end intranet users, but for back office we're still logging in manually (which is fine by me). Attaching a little sample code that seems to make all the magic work. There may be a couple other files/controllers that assist, but this is the bulk of it I believe. (We're on Umbraco 8.17.)
using Microsoft.Owin;
using Owin;
using System.Collections.Generic;
using System.Configuration;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using IdentityModel.Client;
using System.Security.Claims;
using System;
using System.Linq;
using Microsoft.AspNet.Identity.Owin;
using System.Threading.Tasks;
using UmbracoIdentity;
using intranet.Models.UmbracoIdentity;
using intranet;
using Umbraco.Core.Composing;
using System.Web.Security;
[assembly: OwinStartup("MyOwinStartup", typeof(MyOwinStartup))]
namespace intranet
{
public class MyOwinStartup : UmbracoIdentityOwinStartupBase
{
private readonly string clientId = ConfigurationManager.AppSettings["okta:ClientId"];
private readonly string redirectUri = ConfigurationManager.AppSettings["okta:RedirectUri"];
private readonly string authority = ConfigurationManager.AppSettings["okta:OrgUri"];
private readonly string clientSecret = ConfigurationManager.AppSettings["okta:ClientSecret"];
private readonly string postLogoutRedirectUri = ConfigurationManager.AppSettings["okta:PostLogoutRedirectUri"];
protected override void ConfigureUmbracoUserManager(IAppBuilder app)
{
base.ConfigureUmbracoUserManager(app);
//Single method to configure the Identity user manager for use with Umbraco
app.ConfigureUserManagerForUmbracoMembers<UmbracoApplicationMember>();
//Single method to configure the Identity user manager for use with Umbraco
app.ConfigureRoleManagerForUmbracoMembers<UmbracoApplicationRole>();
}
protected override void ConfigureUmbracoAuthentication(IAppBuilder app)
{
base.ConfigureUmbracoAuthentication(app);
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
var cookieOptions = CreateFrontEndCookieAuthenticationOptions();
cookieOptions.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<UmbracoMembersUserManager<UmbracoApplicationMember>, UmbracoApplicationMember, int>(
TimeSpan.FromMinutes(30),
(manager, user) => user.GenerateUserIdentityAsync(manager),
identity =>
{
var email = identity.Claims.FirstOrDefault(c => c.Type == "email")?.Value;
var member = Current.Services.MemberService.GetByEmail(email);
return member.Id;
})
};
app.UseCookieAuthentication(cookieOptions, PipelineStage.Authenticate);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ApplicationCookie);
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
ClientId = clientId,
ClientSecret = clientSecret,
Authority = authority,
RedirectUri = redirectUri,
ResponseType = OpenIdConnectResponseType.CodeIdToken,
Scope = OpenIdConnectScope.OpenIdProfile + " email",
PostLogoutRedirectUri = postLogoutRedirectUri,
TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
},
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = async n =>
{
// Exchange code for access and ID tokens
var tokenClient = new TokenClient(authority + "/v1/token", clientId, clientSecret);
var tokenResponse = await tokenClient.RequestAuthorizationCodeAsync(n.Code, redirectUri);
if (tokenResponse.IsError)
{
throw new Exception(tokenResponse.Error);
}
var userInfoClient = new UserInfoClient(authority + "/v1/userinfo");
var userInfoResponse = await userInfoClient.GetAsync(tokenResponse.AccessToken);
var claims = new List<Claim>();
claims.AddRange(userInfoResponse.Claims);
claims.Add(new Claim("id_token", tokenResponse.IdentityToken));
claims.Add(new Claim("access_token", tokenResponse.AccessToken));
if (!string.IsNullOrEmpty(tokenResponse.RefreshToken))
{
claims.Add(new Claim("refresh_token", tokenResponse.RefreshToken));
}
n.AuthenticationTicket.Identity.AddClaims(claims);
var email = claims.FirstOrDefault(c => c.Type == "email")?.Value;
var name = claims.FirstOrDefault(c => c.Type == "name")?.Value;
// create member if not exists already.
var member = Services.MemberService.GetByEmail(email);
if (member == null)
{
member = Services.MemberService.CreateMember(email, email, name, "Member");
Services.MemberService.Save(member);
}
// login memeber
FormsAuthentication.SetAuthCookie(email, true);
return;
},
RedirectToIdentityProvider = n =>
{
// If signing out, add the id_token_hint
if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
{
var idTokenClaim = n.OwinContext.Authentication.User.FindFirst("id_token");
if (idTokenClaim != null)
{
n.ProtocolMessage.IdTokenHint = idTokenClaim.Value;
}
}
return Task.CompletedTask;
}
},
});
}
}
}
How can I add [Authorize] to all front-end pages [via controller maybe]
Odd question, but I'm trying to secure an Umbraco 8.1.4 intranet by using Okta to auto-login staff with their Windows credentials (using essentially these steps).
I've modified a MyOwinStartup.cs to include the Okta code, plus added the line "GlobalFilters.Filters.Add(new AuthorizeAttribute())", which forces all controllers to require authorization. This approach works fine for the front end, but BackOffice users find that after login they can't do anything else (404 errors etc).
Short of implementing the full UmbracoIdentity approach (trying to avoid the whole Members approach, don't really need that level of login control), is there a way to maybe include a surface controller on every page to which we could prepend the [Authorize] keyword? I'd then remove the GlobalFilters code from MyOwinStartup.
Or if there's a better (but still sorta easy) approach, would love to hear what others recommend.
Hi Eric
I'm not sure if this is what you need for what you are trying to achieve but you can replace the default RenderMvcController that Umbraco uses with your own implementation... Eg create a new controller; inherit RenderMvcController and set it as the default during composing...
See here for how:
https://our.umbraco.com/Documentation/Implementation/Default-Routing/Controller-Selection/
Still feel like I'm so close yet so far. Okta works for auto-logging in people to front-end pages (not as Members, strictly as Windows-authenticated users), but the BackOffice throws a bunch of errors after login:
Per Marc's suggestion, I replaced the default RenderMvcController to include the [Authorize] parameter, see code below from my App_Start/SetDefaultMvcControllerComposer.cs. This does seem to correctly trigger Okta to log users in when they first hit any front-end page.
Web.config has these lines which pertain to Okta login:
And lastly, App_Start/MyOwinStartup.cs which has both recently-added Okta code, and some earlier code for logging in Backoffice users:
If it's actually better/easier to incorporate Okta login into the UmbracoIdentity code example, we're happy to go that route also, it just seemed like more than we needed since we're not really using the Members section of Umbraco in this intranet, and only are needing Windows Authentication (and can't just set the overall app in IIS to use Windows Authentication because of some mobile and other out-of-office users).
Did you get this working? We may be going down the same pathway
Any updates around this? I seem to have the same problem in reverse with the Google Authenticator, I've managed to get it working for the back office but not the front end. Although I only moved to using the Google Auth because I had trouble getting Okta to work so if you've managed that then I'd really appreciate any advice?
We ended up contracting with FYIN to finish our Okta integration. Works great for front-end intranet users, but for back office we're still logging in manually (which is fine by me). Attaching a little sample code that seems to make all the magic work. There may be a couple other files/controllers that assist, but this is the bulk of it I believe. (We're on Umbraco 8.17.)
Web.config:
App_Start/MyOwinStartup.cs:
This is fantastic, thank you very much Eric.
is working on a reply...