Try our conversational search powered by Generative AI!

EPiServer and openid connect

Vote:
 

Hi!

So I have some more questions around the openId connect. I managed to authenticate, following this guide https://www.johanbostrom.se/blog/setting-up-episerver-to-use-openid-connect-with-identityserver.

But I got stuck here. How do I validate if the current user is authenticated. And how do I now log in to edit and admin mode. Do I use claims? If so - how.

Appreciate any help!

#198035
Oct 19, 2018 8:08
Vote:
 

Are you using IdentityServer4? Have you implemented role claims on that side?

This is a later and better post to follow IMHO:
https://swapcode.wordpress.com/2018/09/24/using-openid-connect-with-episerver/

#198046
Oct 19, 2018 9:46
Vote:
 

I am using an external authentication service: https://difi.github.io/idporten-oidc-dokumentasjon/index.html

#198047
Oct 19, 2018 10:03
Vote:
 

There seems to be no special claim type for roles so you either need to ask if they can add roles OR add role claims to the authentication ticket by yourself (based on some other data) in the Epi site. There's an example in the blog post I linked.

Based on the data below I recommend to use ResponseType = "code id_token" or if that gives an error just use "id_token".

From https://oidc.difi.no/idporten-oidc-provider/.well-known/openid-configuration

{
  "issuer": "https://oidc.difi.no/idporten-oidc-provider/",
  "authorization_endpoint": "https://oidc.difi.no/idporten-oidc-provider/authorize",
  "token_endpoint": "https://oidc.difi.no/idporten-oidc-provider/token",
  "end_session_endpoint": "https://oidc.difi.no/idporten-oidc-provider/endsession",
  "revocation_endpoint": "https://oidc.difi.no/idporten-oidc-provider/revoke",
  "jwks_uri": "https://oidc.difi.no/idporten-oidc-provider/jwk",
  "response_types_supported": [
    "code",
    "id_token",
    "id_token token",
    "token"
  ],
  "response_modes_supported": [
    "query",
    "form_post",
    "fragment"
  ],
  "subject_types_supported": [
    "pairwise"
  ],
  "id_token_signing_alg_values_supported": [
    "RS256"
  ],
  "userinfo_endpoint": "https://oidc.difi.no/idporten-oidc-provider/userinfo",
  "scopes_supported": [
    "openid",
    "profile"
  ],
  "ui_locales_supported": [
    "nb",
    "nn",
    "en",
    "se"
  ],
  "acr_values_supported": [
    "Level3",
    "Level4"
  ],
  "frontchannel_logout_supported": true,
  "frontchannel_logout_session_supported": true,
  "introspection_endpoint": "https://oidc.difi.no/idporten-oidc-provider/tokeninfo"
}
#198048
Oct 19, 2018 10:27
Vote:
 

So, back to the authentication. It doesn't seem like the authentication process completes. This is mye code:

{
  public class Startup
  {
    private const string UrlLogout = "/logout";
    private const string UrlLogin = "/login";

    private const string OicClientId = "<myclientid>";
    private const string OicAuthority = "<myauthority>";
    private const string OicScopes = "openid";

    private const string OicResponseType = "code";

    private const string redirectUri = "<myredirecturi>";

    public void Configuration(IAppBuilder app)
    {
      Logger.Current.LogDebug("Configuration startup running...");

      app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

      app.UseCookieAuthentication(new CookieAuthenticationOptions());

      app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
      {
        ClientId = OicClientId,
        Authority = OicAuthority,
        PostLogoutRedirectUri = OicPostLogoutRedirectUri,
        ResponseType = OicResponseType,
        Scope = OicScopes,
        RequireHttpsMetadata = false,
        RedirectUri = redirectUri,

        
        TokenValidationParameters = new TokenValidationParameters
        {
          ValidateIssuer = false,
          NameClaimType = ClaimTypes.NameIdentifier,
          RoleClaimType = ClaimTypes.Role
        },
        Notifications = new OpenIdConnectAuthenticationNotifications
        {
          AuthenticationFailed = context =>
          {
            Logger.Current.LogDebug("Authentication failed: " + context.Exception.Message);
            context.HandleResponse();
            context.Response.Write(context.Exception.Message);
            return Task.FromResult(0);
          },
          RedirectToIdentityProvider = context =>
          {
            Logger.Current.LogDebug("Redirecting...");

            if (context.ProtocolMessage.RedirectUri == null)
            {
              var currentUrl = SiteDefinition.Current.SiteUrl;
              context.ProtocolMessage.RedirectUri = new UriBuilder(
                currentUrl.Scheme,
                currentUrl.Host,
                currentUrl.Port,
                HttpContext.Current.Request.Url.AbsolutePath).ToString();
            }

            Logger.Current.LogDebug("Response: " + context.OwinContext.Response.StatusCode);
            Logger.Current.LogDebug("Is authenticated: " + context.OwinContext.Authentication.User.Identity.IsAuthenticated);

            if (context.OwinContext.Response.StatusCode == 401 &&
              context.OwinContext.Authentication.User.Identity.IsAuthenticated)
            {
              context.OwinContext.Response.StatusCode = 403;
              context.HandleResponse();
            }
            return Task.FromResult(0);
          },
          SecurityTokenValidated = ctx =>
          {
            Logger.Current.LogDebug("Redirect uri: " + ctx.AuthenticationTicket.Properties.RedirectUri);

            var redirectUri = new Uri(ctx.AuthenticationTicket.Properties.RedirectUri,
              UriKind.RelativeOrAbsolute);
            if (redirectUri.IsAbsoluteUri)
              ctx.AuthenticationTicket.Properties.RedirectUri = redirectUri.PathAndQuery;
            
            ServiceLocator.Current.GetInstance<OicSynchronizingUserService>()
              .SynchronizeAsync(ctx.AuthenticationTicket.Identity);

            return Task.FromResult(0);
          },
          SecurityTokenReceived = ctx =>
          {
            Logger.Current.LogDebug("Seurity token received");
            return Task.FromResult(0);
          }
        }
      });

      app.UseStageMarker(PipelineStage.Authenticate);

      Logger.Current.LogDebug("UrlLogin: " + UrlLogin);

      app.Map(UrlLogin, config =>
      {
        config.Run(ctx =>
        {
          Logger.Current.LogDebug("Login - user not null?: " + ctx.Authentication.User != null);
          
          if (ctx.Authentication.User == null || !ctx.Authentication.User.Identity.IsAuthenticated)
            ctx.Response.StatusCode = 401;
          else
            ctx.Response.Redirect("/");

          Logger.Current.LogDebug("Login - name: " + ctx.Authentication.User.Identity.Name);
          Logger.Current.LogDebug("Login - statuscode: " + ctx.Response.StatusCode);
          Logger.Current.LogDebug("Login - isauthenticated: " + ctx.Authentication.User.Identity.IsAuthenticated);
          return Task.FromResult(0);
        });
      });

      Logger.Current.LogDebug("map url login finished");

      app.Map(UrlLogout, config =>
      {
        config.Run(ctx =>
        {
          ctx.Authentication.SignOut();
          return Task.FromResult(0);
        });
      });

      Logger.Current.LogDebug("map url logout finished");


    }
  }

But I get 401 and the user is never authenticated. According to the guide I followed, this should be enough? This is an extract from my log:

2018-10-20 09:17:50,958 [77] DEBUG DW.NA.Web: Login - user: False
2018-10-20 09:17:50,958 [77] DEBUG DW.NA.Web: Login - user: False
2018-10-20 09:17:50,962 [77] DEBUG DW.NA.Web: Login - name: 
2018-10-20 09:17:50,962 [77] DEBUG DW.NA.Web: Login - name: 
2018-10-20 09:17:50,965 [77] DEBUG DW.NA.Web: Login - statuscode: 401
2018-10-20 09:17:50,965 [77] DEBUG DW.NA.Web: Login - statuscode: 401
2018-10-20 09:17:50,967 [77] DEBUG DW.NA.Web: Login - isauthenticated: False
2018-10-20 09:17:50,967 [77] DEBUG DW.NA.Web: Login - isauthenticated: False
2018-10-20 09:17:51,854 [57] DEBUG DW.NA.Web: Redirecting...
2018-10-20 09:17:51,854 [57] DEBUG DW.NA.Web: Redirecting...
2018-10-20 09:17:51,857 [57] DEBUG DW.NA.Web: Response: 401
2018-10-20 09:17:51,857 [57] DEBUG DW.NA.Web: Response: 401
2018-10-20 09:17:51,860 [57] DEBUG DW.NA.Web: Is authenticated: False
2018-10-20 09:17:51,860 [57] DEBUG DW.NA.Web: Is authenticated: False

The AuthenticationFailed, SecurityTokenValidated, SecurityTokenReceived never runs.

Even though I successfully log in with my test user and gets redirected back to my solution.

What am I missing?

#198083
Oct 20, 2018 9:35
Vote:
 

You need to use ResponseType = "code id_token" or something else than what you got. The Owin OIDC package doesn't support just "code".

#198085
Oct 20, 2018 20:03
Vote:
 

It's the only responsetype supported. No mather what other combination I try, I get this error message: 

'unsupported_response_type'.

Should I ask the provider to change som settings, or do I have to change something on my side?

#198086
Oct 21, 2018 7:37
Vote:
 

Hi Torunn, if you get "unsupported response type" when using the "code id_token" response type then you definetly should contact the provider. Maybe they have just forgotten to allow that response type for your client id (at least the allowed response types are defined per client in IdentityServer: Grant Types and the above linked post IdentityServer client configuration).

#198087
Oct 21, 2018 9:36
Vote:
 

People have worked on supporting "code". Not officially accepted yet though.

https://github.com/adefalque/AspNetKatana/tree/feature/oidauthcode

#198107
Oct 22, 2018 9:13
Vote:
 

To update you, I got the provider to create a new environment with responsetype "public" . This allowed me to use the id_token responsetype, which led to a successfull authentication. Thank you so much for your help:)

#198585
Oct 31, 2018 14:18
Vote:
 

Great!

One of the main things with any Federated Security setup is that things need to match exactly on both sides which often leads to a bit of extra headscratching when things aren't working. Especially if you don't have access to the IDP.

#198588
Oct 31, 2018 14:33
Vote:
 

Headscratching indeed;)

#198595
Oct 31, 2018 14:53
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.