2
votes

I am currently involved in development of an Angular4 SPA application connected to a .NET CORE 1.1 WebApi using IdentityServer4 as it's authentication service.

On the Angular side we are using the Oidc client from Damien Bod 1.2.1 - https://github.com/damienbod/angular-auth-oidc-client.

We have managed to successfully setup and login via IdentityServer. The problem arises that are exactly 30min we are getting a SessionTimeout on the IdentityServer and from there the Oidc client obtains a 401 and so is now not authorized.

The Oidc client is configured to use Silent Renew so is supposed to keep the session open. However this does not appear to be the case. Comments from the Oidc author Damien Bod seem to indicate that the IdentityServer4 session has timedout.

Question: How can we ensure the IdentityServer4 session does not time out when using the Silent Renew of the Oidc package.

Setup on our IdentityServer4 side:

  "ClientId": "MyId",
      "ClientName": "MyName",
      "AllowedGrantTypes": [ "implicit" ],
      "RequireConsent": false,
      "AllowedScopes": [ "openid", "profile", "email", "role", "api.write", "api.read", "offline_access" ],
      "RedirectUris": [ "https://localhost:4200" ],
      "PostLogoutRedirectUris": [ "https://localhost:4200" ],
      "LogoutUri": "https://localhost:4200",
      "AllowedCorsOrigins": [ "http://localhost:4200", "https://localhost:4200" ],
      "AllowOfflineAccess": true,
      "AllowAccessTokensViaBrowser": true,
      "AccessTokenType": 0

Setup on our client side:

let openIDImplicitFlowConfiguration = new OpenIDImplicitFlowConfiguration();
    openIDImplicitFlowConfiguration.stsServer = environment.stsServer;
    openIDImplicitFlowConfiguration.redirect_url = environment.redirect_url;
    openIDImplicitFlowConfiguration.client_id = 'MyName';
    openIDImplicitFlowConfiguration.response_type = 'id_token token';
    openIDImplicitFlowConfiguration.scope = 'openid email profile role api.write api.read offline_access';
    openIDImplicitFlowConfiguration.post_logout_redirect_uri = environment.post_logout_redirect_uri;
    openIDImplicitFlowConfiguration.start_checksession = false;
    openIDImplicitFlowConfiguration.silent_renew = true;
    openIDImplicitFlowConfiguration.startup_route = '/home';
    openIDImplicitFlowConfiguration.forbidden_route = '/forbidden';
    openIDImplicitFlowConfiguration.unauthorized_route = '/unauthorized';
    openIDImplicitFlowConfiguration.log_console_warning_active = true;
    openIDImplicitFlowConfiguration.log_console_debug_active = true;
    openIDImplicitFlowConfiguration.max_id_token_iat_offset_allowed_in_seconds = 10;
    openIDImplicitFlowConfiguration.override_well_known_configuration = false;
    openIDImplicitFlowConfiguration.override_well_known_configuration_url = environment.well_known_config_url;
    openIDImplicitFlowConfiguration.storage = localStorage;

    this.oidcSecurityService.setupModule(openIDImplicitFlowConfiguration);

Log files from IdentityServer which shows the timeout:

2017-08-21 11:06:46.910 +12:00 [Information] Request starting HTTP/1.1 GET http://localhost:44345/connect/authorize?response_type=id_token%20token&client_id=AuctionX.Web.Ui.Client.Ng&redirect_uri=http://localhost:4200&scope=openid%20email%20profile%20role%20api.write%20api.read%20offline_access&nonce=N0.008974817642323441503270406807&state=15032704068070.2664008961443083  
2017-08-21 11:06:46.929 +12:00 [Information] Executed DbCommand (1ms) [Parameters=[@__get_Item_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Id], [e].[AccessFailedCount], [e].[ConcurrencyStamp], [e].[Email], [e].[EmailConfirmed], [e].[LockoutEnabled], [e].[LockoutEnd], [e].[NormalizedEmail], [e].[NormalizedUserName], [e].[PasswordHash], [e].[PhoneNumber], [e].[PhoneNumberConfirmed], [e].[SecurityStamp], [e].[TwoFactorEnabled], [e].[UserName]
FROM [AspNetUsers] AS [e]
WHERE [e].[Id] = @__get_Item_0
2017-08-21 11:06:46.938 +12:00 [Information] AuthenticationScheme: "Identity.Application" signed out.
2017-08-21 11:06:46.944 +12:00 [Information] AuthenticationScheme: "Identity.External" signed out.
2017-08-21 11:06:46.950 +12:00 [Information] AuthenticationScheme: "Identity.TwoFactorUserId" signed out.
2017-08-21 11:06:46.953 +12:00 [Information] "Identity.Application" was not authenticated. Failure message: "No principal."

Log files from the Oidc Client
VM543 vendor.bundle.js:441 onWellKnownEndpointsLoaded
VM543 vendor.bundle.js:441 IsAuthorized: id_token isTokenExpired, start silent renew if active
VM543 vendor.bundle.js:441 BEGIN refresh session Authorize
VM543 vendor.bundle.js:441 RefreshSession created. adding myautostate: 15032774526950.18444551521534458
VM543 vendor.bundle.js:441 startRenew for URL:https://localhost:44345/connect/authorize?response_type=id_token%20token&client_id=AuctionX.Web.Ui.Client.Ng&redirect_uri=http://localhost:4200&scope=openid%20email%20profile%20role%20api.write%20api.read%20offline_access&nonce=N0.055432655304242351503277452695&state=15032774526950.18444551521534458
VM543 vendor.bundle.js:441 STS server: https://localhost:44345
VM543 vendor.bundle.js:441 {issuer: "https://localhost:44345", jwks_uri: "https://localhost:44345/.well-known/openid-configuration/jwks", authorization_endpoint: "https://localhost:44345/connect/authorize", token_endpoint: "https://localhost:44345/connect/token", userinfo_endpoint: "https://localhost:44345/connect/userinfo", …}
VM543 vendor.bundle.js:441 AuthWellKnownEndpoints already defined
VM543 vendor.bundle.js:441 BEGIN authorizedCallback, no auth data
VM543 vendor.bundle.js:441 {id_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOT…5P2zqgYNYQOuq36tWm37eLOnZ7PE_TiQoHpX9iEbyaZQQmlPg", access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOT…pU0eoTqFx9sUbjRw__r8z_-FjaTQH0acMb9K8uKzqOn5dgxnw", token_type: "Bearer", expires_in: "120", scope: "openid%20email%20profile%20role%20api.write%20api.read%20offline_access", …}
VM543 vendor.bundle.js:441 authorizedCallback created, begin token validation
VM543 vendor.bundle.js:441 jwks_uri: https://localhost:44345/.well-known/openid-configuration/jwks
VM543 vendor.bundle.js:126701 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
VM543 vendor.bundle.js:441 validate_id_token_iat_max_offset: 2328 < 10000
VM543 vendor.bundle.js:441 From the server:DsQ3fMYhzDrjDQJPMfqRzg
VM543 vendor.bundle.js:441 client validation not decoded:DsQ3fMYhzDrjDQJPMfqRzg
VM543 vendor.bundle.js:441 AuthorizedCallback token(s) validated, continue
VM543 vendor.bundle.js:441 eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOTFhMjFiYTA3NjVkM2QzNDhjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDMyNzc0NTMsImV4cCI6MTUwMzI3NzU3MywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUiLCJhdWQiOlsiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUvcmVzb3VyY2VzIiwiYXVjdGlvblguYXBpIl0sImNsaWVudF9pZCI6IkF1Y3Rpb25YLldlYi5VaS5DbGllbnQuTmciLCJzdWIiOiI1QkU4NjM1OS0wNzNDLTQzNEItQUQyRC1BMzkzMjIyMkRBQkUiLCJhdXRoX3RpbWUiOjE1MDMyNzU5NzQsImlkcCI6ImxvY2FsIiwicm9sZSI6ImFkbWluIiwic2NvcGUiOlsib3BlbmlkIiwiZW1haWwiLCJwcm9maWxlIiwicm9sZSIsImFwaS53cml0ZSIsImFwaS5yZWFkIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.ZvIho_FnuW_27b_sgLL_nJj_45tqlO4oMSkgFKj8cDObR--4OC1wESgo9jH6vjPR4Gx42DK5iiryaW8X91Yr_X8l-rcwECMacsXR_aZYCVKOC5kORLNHEzSg1ha0vI7EQCn2wuLn_z-ljJGVhxMbc2tI_kCt4abuChA0AryKt0EFCQ_11rvZry_yW49nlUBO_WgkgSB4R5x9MHQiWKlW6UOW-1t790QoARQjyp9WJ0AsHc4xtBjOmLJzOb7kTjp7ND5zrM7QVBK5HOewaV4fL7cVjWGXEZmH9m9D3pU0eoTqFx9sUbjRw__r8z_-FjaTQH0acMb9K8uKzqOn5dgxnw
VM543 vendor.bundle.js:441 eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOTFhMjFiYTA3NjVkM2QzNDhjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDMyNzc0NTMsImV4cCI6MTUwMzI3NzU0MywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUiLCJhdWQiOiJBdWN0aW9uWC5XZWIuVWkuQ2xpZW50Lk5nIiwibm9uY2UiOiJOMC4wNTU0MzI2NTUzMDQyNDIzNTE1MDMyNzc0NTI2OTUiLCJpYXQiOjE1MDMyNzc0NTMsImF0X2hhc2giOiJEc1EzZk1ZaHpEcmpEUUpQTWZxUnpnIiwic2lkIjoiMWJkNjQ0YmVhMjQwZjM1MDc2YzQ5NzVjOTg0ZjI1N2IiLCJzdWIiOiI1QkU4NjM1OS0wNzNDLTQzNEItQUQyRC1BMzkzMjIyMkRBQkUiLCJhdXRoX3RpbWUiOjE1MDMyNzU5NzQsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.pExwBcxTQiT2nY38l5f6ZGNs4gzLTYZlUEO6sDl_Q2fPmzjppKn-7yU8bhjCy6xZKKuOT3pRO3JmZFEln1CDBfJqTsOg4UH8tu0MIIeMkiIBwjMooqb-ocN6JPwkrr-CuSk90xsQmGPqdaSRLC7IHFQ2VPq5Ic7b9Jd4CXIDZQbBKdR2PEC8n2Rfl-ayDOEXzOni8ylQ5ksu28eRicv7-HYimnF3Xc63xiBIC1NH4OofxQoqQRdBL2j8OJDKXQY6oDZxUNBLsIf1-jnM_MUTnr4tHoiX-XIhbZuTa5P2zqgYNYQOuq36tWm37eLOnZ7PE_TiQoHpX9iEbyaZQQmlPg
VM543 vendor.bundle.js:441 storing to storage, getting the roles
VM543 vendor.bundle.js:441 onWellKnownEndpointsLoaded
VM543 vendor.bundle.js:441 IsAuthorized: id_token isTokenExpired, start silent renew if active
VM543 vendor.bundle.js:441 BEGIN refresh session Authorize
VM543 vendor.bundle.js:441 RefreshSession created. adding myautostate: 15032775466960.9369647619628338
VM543 vendor.bundle.js:441 startRenew for URL:https://localhost:44345/connect/authorize?response_type=id_token%20token&client_id=AuctionX.Web.Ui.Client.Ng&redirect_uri=http://localhost:4200&scope=openid%20email%20profile%20role%20api.write%20api.read%20offline_access&nonce=N0.223876239755147031503277546696&state=15032775466960.9369647619628338
VM543 vendor.bundle.js:441 STS server: https://localhost:44345
VM543 vendor.bundle.js:441 {issuer: "https://localhost:44345", jwks_uri: "https://localhost:44345/.well-known/openid-configuration/jwks", authorization_endpoint: "https://localhost:44345/connect/authorize", token_endpoint: "https://localhost:44345/connect/token", userinfo_endpoint: "https://localhost:44345/connect/userinfo", …}
VM543 vendor.bundle.js:441 AuthWellKnownEndpoints already defined
VM543 vendor.bundle.js:441 BEGIN authorizedCallback, no auth data
VM543 vendor.bundle.js:441 {id_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOT…y0UvzWAIigtnoy8ho-RvIHCVLfFNdrS_YockJLRhwZZHtOgVg", access_token: "eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOT…Q4CSsXVqa58bI7tROqruKxn9bb3q7zPIV-KSTOhXGAFo7ZN7Q", token_type: "Bearer", expires_in: "120", scope: "openid%20email%20profile%20role%20api.write%20api.read%20offline_access", …}
VM543 vendor.bundle.js:441 authorizedCallback created, begin token validation
VM543 vendor.bundle.js:441 jwks_uri: https://localhost:44345/.well-known/openid-configuration/jwks
VM543 vendor.bundle.js:126701 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
VM543 vendor.bundle.js:441 validate_id_token_iat_max_offset: 2334 < 10000
VM543 vendor.bundle.js:441 From the server:VBff-XldgCju7j-ghbcK3g
VM543 vendor.bundle.js:441 client validation not decoded:VBff-XldgCju7j-ghbcK3g
VM543 vendor.bundle.js:441 AuthorizedCallback token(s) validated, continue
VM543 vendor.bundle.js:441 eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOTFhMjFiYTA3NjVkM2QzNDhjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDMyNzc1NDcsImV4cCI6MTUwMzI3NzY2NywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUiLCJhdWQiOlsiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUvcmVzb3VyY2VzIiwiYXVjdGlvblguYXBpIl0sImNsaWVudF9pZCI6IkF1Y3Rpb25YLldlYi5VaS5DbGllbnQuTmciLCJzdWIiOiI1QkU4NjM1OS0wNzNDLTQzNEItQUQyRC1BMzkzMjIyMkRBQkUiLCJhdXRoX3RpbWUiOjE1MDMyNzU5NzQsImlkcCI6ImxvY2FsIiwicm9sZSI6ImFkbWluIiwic2NvcGUiOlsib3BlbmlkIiwiZW1haWwiLCJwcm9maWxlIiwicm9sZSIsImFwaS53cml0ZSIsImFwaS5yZWFkIiwib2ZmbGluZV9hY2Nlc3MiXSwiYW1yIjpbInB3ZCJdfQ.Xy1X3CeEaTYAWNKkYrIKKhZiEYkRnGJve1pP2kDO5qRg5-Qe-g9h-0BB-j5TeXE1VIrBOJ-1vr6Vkr28jfyAz7t02rHnK9Vs94xFc2H8UNcF98YBT-7GKqRd-FB1L3lQqtZWMku4b01qmIPSjUThzShcdgrbOsIpwdxC3UB-Ziram6EfUme10Wpb2J1vto7rEKcurQ6LZI3645x0rTlGS2fXU7x0UQxfxhAX9VNYwAreT8T2-O4mLzr9Ejbd-kMEfXNALIUUJ3KKRmGOGCHM5fwHzsuX67gIqJXueQ4CSsXVqa58bI7tROqruKxn9bb3q7zPIV-KSTOhXGAFo7ZN7Q
VM543 vendor.bundle.js:441 eyJhbGciOiJSUzI1NiIsImtpZCI6IjJlY2ZkYTVhMmI1OTAwOTFhMjFiYTA3NjVkM2QzNDhjIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDMyNzc1NDcsImV4cCI6MTUwMzI3NzYzNywiaXNzIjoiaHR0cHM6Ly9sb2NhbGhvc3Q6NDQzNDUiLCJhdWQiOiJBdWN0aW9uWC5XZWIuVWkuQ2xpZW50Lk5nIiwibm9uY2UiOiJOMC4yMjM4NzYyMzk3NTUxNDcwMzE1MDMyNzc1NDY2OTYiLCJpYXQiOjE1MDMyNzc1NDcsImF0X2hhc2giOiJWQmZmLVhsZGdDanU3ai1naGJjSzNnIiwic2lkIjoiMWJkNjQ0YmVhMjQwZjM1MDc2YzQ5NzVjOTg0ZjI1N2IiLCJzdWIiOiI1QkU4NjM1OS0wNzNDLTQzNEItQUQyRC1BMzkzMjIyMkRBQkUiLCJhdXRoX3RpbWUiOjE1MDMyNzU5NzQsImlkcCI6ImxvY2FsIiwiYW1yIjpbInB3ZCJdfQ.f-PzKxDafEIRPIz_qL_xtbI4QlDybyyRWMhnxUaNzOS1SJGVLVY1zpx89Y0MHlSe8NSZgtBOieB_Wr52nKZLm85ItMOCSpr5I5uZBi_mdufBEJWzOfbcnPT53pvpETwBVxSAOJvJXq-XxC-rxCeoHs7xd57M57RWa_Wla_rgh2-dVdscHHxA7fKDToEM_SpLgmFlI4QWV3DnMtkNWVzXkSNq1Iv5AOvtfI_j5Dz5XgsJAoyI1vWQHZqRuNO8_TK0g2oudvfv-xji1Uc_oFA_0rEdfoacNoyAwe4vky0UvzWAIigtnoy8ho-RvIHCVLfFNdrS_YockJLRhwZZHtOgVg
VM543 vendor.bundle.js:441 storing to storage, getting the roles
VM543 vendor.bundle.js:441 onWellKnownEndpointsLoaded
home:1 Refused to display 'https://localhost:44345/account/login?returnUrl=%2Fconnect%2Fauthorize%2Flogin%3Fresponse_type%3Did_token%2520token%26client_id%3DAuctionX.Web.Ui.Client.Ng%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26scope%3Dopenid%2520email%2520profile%2520role%2520api.write%2520api.read%2520offline_access%26nonce%3DN0.481244061017480631503277824820%26state%3D15032778248200.2571680787467199' in a frame because it set 'X-Frame-Options' to 'sameorigin'.
2
Did you guys found the solution for this problem? Same here... :=(totesz09

2 Answers

1
votes

The problem may be in method you are using when signing in the user.

If you use HttpContext.SignInAsync(...) then you should explicitly pass the SecurityStamp claim to it:

var secStampClaim = new Claim(
    _userManager.Options.ClaimsIdentity.SecurityStampClaimType,
    user.SecurityStamp);
await HttpContext.SignInAsync(user.Id.ToString(), secStampClaim);

But I think it's better just to use SignInManager for that, it will build claims principal and add SecurityStamp claim to cookie:

await _signInManager.SignInAsync(user, false);
0
votes

It's possible this is not a problem with the UI client at all but rather that the cookie is being invalidated on the IdentityServer side and so effectively signing the user out.

The setting which seems to extend this is the SecurityStampValidationInterval such as (to 1hr):

 services.AddIdentity<IdentityUser, IdentityRole>(
                        options =>
                        {
                            options.Cookies.ApplicationCookie.AuthenticationScheme = cookieAuth.AuthenticationScheme;

                            options.SecurityStampValidationInterval = TimeSpan.FromHours(1);

                            options.Password.RequiredLength = 8;
                            options.Password.RequireUppercase = true;
                            options.Password.RequireLowercase = true;
                            options.Password.RequireNonAlphanumeric = true; 
                            options.Password.RequireDigit = true;
                        })

However this is not ideal as the user is still logged out after 1 hour even though nothing has changed. Why this is the case is yet to be determined.