Example #1
0
        /// <summary>
        /// Create the claims to be used in the back-channel logout token.
        /// </summary>
        /// <param name="request"></param>
        /// <returns>The claims to include in the token.</returns>
        protected Task <IEnumerable <Claim> > CreateClaimsForTokenAsync(BackChannelLogoutRequest request)
        {
            if (request.SessionIdRequired && request.SessionId == null)
            {
                throw new ArgumentException("Client requires SessionId", nameof(request.SessionId));
            }

            var json = "{\"" + OidcConstants.Events.BackChannelLogout + "\":{} }";

            var claims = new List <Claim>
            {
                new Claim(JwtClaimTypes.Subject, request.SubjectId),
                new Claim(JwtClaimTypes.Audience, request.ClientId),
                new Claim(JwtClaimTypes.IssuedAt, Clock.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
                new Claim(JwtClaimTypes.JwtId, CryptoRandom.CreateUniqueId(16, CryptoRandom.OutputFormat.Hex)),
                new Claim(JwtClaimTypes.Events, json, IdentityServerConstants.ClaimValueTypes.Json)
            };

            if (request.SessionId != null)
            {
                claims.Add(new Claim(JwtClaimTypes.SessionId, request.SessionId));
            }

            return(Task.FromResult(claims.AsEnumerable()));
        }
Example #2
0
        /// <summary>
        /// Creates the JWT used for the back-channel logout notification.
        /// </summary>
        /// <param name="request"></param>
        /// <returns>The token.</returns>
        protected virtual async Task <string> CreateTokenAsync(BackChannelLogoutRequest request)
        {
            var claims = await CreateClaimsForTokenAsync(request);

            if (claims.Any(x => x.Type == JwtClaimTypes.Nonce))
            {
                throw new InvalidOperationException("nonce claim is not allowed in the back-channel signout token.");
            }

            return(await Tools.IssueJwtAsync(DefaultLogoutTokenLifetime, claims));
        }
        /// <inheritdoc/>
        public async Task <IEnumerable <BackChannelLogoutRequest> > GetBackChannelLogoutNotificationsAsync(LogoutNotificationContext context)
        {
            var backChannelLogouts = new List <BackChannelLogoutRequest>();

            foreach (var clientId in context.ClientIds)
            {
                var client = await _clientStore.FindEnabledClientByIdAsync(clientId);

                if (client != null)
                {
                    if (client.BackChannelLogoutUri.IsPresent())
                    {
                        var back = new BackChannelLogoutRequest
                        {
                            ClientId          = clientId,
                            LogoutUri         = client.BackChannelLogoutUri,
                            SubjectId         = context.SubjectId,
                            SessionId         = context.SessionId,
                            SessionIdRequired = client.BackChannelLogoutSessionRequired
                        };

                        backChannelLogouts.Add(back);
                    }
                }
            }

            if (backChannelLogouts.Any())
            {
                var msg = backChannelLogouts.Select(x => x.LogoutUri).Aggregate((x, y) => x + ", " + y);
                _logger.LogDebug("Client back-channel logout URLs: {0}", msg);
            }
            else
            {
                _logger.LogDebug("No client back-channel logout URLs");
            }

            return(backChannelLogouts);
        }
Example #4
0
        /// <summary>
        /// Creates the form-url-encoded payload (as a dictionary) to send to the client.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        protected async Task <Dictionary <string, string> > CreateFormPostPayloadAsync(BackChannelLogoutRequest request)
        {
            var token = await CreateTokenAsync(request);

            var data = new Dictionary <string, string>
            {
                { OidcConstants.BackChannelLogoutRequest.LogoutToken, token }
            };

            return(data);
        }
Example #5
0
 /// <summary>
 /// Performs the HTTP POST of the logout payload to the client.
 /// </summary>
 /// <param name="client"></param>
 /// <param name="data"></param>
 /// <returns></returns>
 protected virtual Task PostLogoutJwt(BackChannelLogoutRequest client, Dictionary <string, string> data)
 {
     return(HttpClient.PostAsync(client.LogoutUri, data));
 }
Example #6
0
        /// <summary>
        /// Performs the back-channel logout for a single client.
        /// </summary>
        /// <param name="request"></param>
        protected virtual async Task SendLogoutNotificationAsync(BackChannelLogoutRequest request)
        {
            var data = await CreateFormPostPayloadAsync(request);

            await PostLogoutJwt(request, data);
        }