public async void Emulator_MsaHeader_BotAppIdDiffers_ShouldNotValidate()
 {
     string header      = $"Bearer {await new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F").GetTokenAsync()}";
     var    credentials = new SimpleCredentialProvider("00000000-0000-0000-0000-000000000000", "");
     await Assert.ThrowsAsync <UnauthorizedAccessException>(
         async() => await JwtTokenValidation.ValidateAuthHeader(header, credentials, "", null, emptyClient));
 }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                if (await Options.CredentialProvider.IsAuthenticationDisabledAsync())
                {
                    var anonymousPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Role, "Bot") }));
                    var anonynousContext   = new TokenValidatedContext(Context, Scheme, Options)
                    {
                        Principal = anonymousPrincipal
                    };
                    anonynousContext.Success();
                    return(anonynousContext.Result);
                }

                string         authHeader     = Request.Headers["Authorization"];
                ClaimsIdentity claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, Options.CredentialProvider, _httpClient);

                Logger.TokenValidationSucceeded();

                claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "Bot"));
                var principal = new ClaimsPrincipal(claimsIdentity);

                Context.User = principal;
                string jwtToken = JwtTokenExtractor.ExtractBearerTokenFromAuthHeader(authHeader);
                var    tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options)
                {
                    Principal     = principal,
                    SecurityToken = new JwtSecurityToken(jwtToken)
                };

                await Events.TokenValidated(tokenValidatedContext);

                if (tokenValidatedContext.Result != null)
                {
                    return(tokenValidatedContext.Result);
                }

                tokenValidatedContext.Success();
                return(tokenValidatedContext.Result);
            }
            catch (Exception ex)
            {
                Logger.ErrorProcessingMessage(ex);

                var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex
                };

                await Events.AuthenticationFailed(authenticationFailedContext);

                if (authenticationFailedContext.Result != null)
                {
                    return(authenticationFailedContext.Result);
                }

                throw;
            }
        }
        public async Task <(bool IsAuthenticated, string ErrorMessage)> Validate(HttpRequest request)
        {
            if (!request.Headers.TryGetValue("Authorization", out StringValues authorizationHeader))
            {
                return(false, "Missing 'Authorization' header");
            }

            var credential = new SimpleCredentialProvider(
                _configuration.GetValue <string>("Bot:Id"),
                _configuration.GetValue <string>("Bot:Password"));

            try
            {
                var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authorizationHeader, credential, null, null);

                if (!claimsIdentity.IsAuthenticated)
                {
                    return(false, "The request fails to pass auth check.");
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to check authentication.");
                return(false, $"Failed to check authentication: {ex.Message}");
            }

            return(true, string.Empty);
        }
        public async void Emulator_MsaHeader_BotAppIdDiffers_ShouldNotValidate()
        {
            var header      = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlNTUWRoSTFjS3ZoUUVEU0p4RTJnR1lzNDBRMCIsImtpZCI6IlNTUWRoSTFjS3ZoUUVEU0p4RTJnR1lzNDBRMCJ9.eyJhdWQiOiIzOTYxOWE1OS01YTBjLTRmOWItODdjNS04MTZjNjQ4ZmYzNTciLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kNmQ0OTQyMC1mMzliLTRkZjctYTFkYy1kNTlhOTM1ODcxZGIvIiwiaWF0IjoxNTE4MTIzMTQxLCJuYmYiOjE1MTgxMjMxNDEsImV4cCI6MTUxODEyNzA0MSwiYWlvIjoiWTJOZ1lQZ1djOSsrenJvaW9QM28rZmw2OWR1c0FBPT0iLCJhcHBpZCI6IjM5NjE5YTU5LTVhMGMtNGY5Yi04N2M1LTgxNmM2NDhmZjM1NyIsImFwcGlkYWNyIjoiMSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2Q2ZDQ5NDIwLWYzOWItNGRmNy1hMWRjLWQ1OWE5MzU4NzFkYi8iLCJ0aWQiOiJkNmQ0OTQyMC1mMzliLTRkZjctYTFkYy1kNTlhOTM1ODcxZGIiLCJ1dGkiOiJPVXE3M1lSbGtFcVoxQ3p2U3FZQkFBIiwidmVyIjoiMS4wIn0.B0t4sSsqIQ3IT2rfpZXqAdAGJSr3aihwk-jJd8as2pAoeQVcQNir_Anvvnjbo5MsB0DCyWFa9xnEmBRiTW_Ww97Z9bZhnCXq4D4vN8dmgEMV_Aci1tI4agy3coCX4fBRc76SHjqJ_ucl850aqR3d_0sfl0TPoDclE4jWssX2YTNzUAMEgisbYe9xv8FfK7AUR8ABS1teTfnWGVYyVFgC7vptSjw-de8sgz7pv8vVtLEKBrrb1FBSzHbbnZ-cQaLLHeIM4agamXf4w45o7_1uHorrp1Tg5oPrsbiayC-dt4lpC9smU5agpyUWCorKZI0Fp3aryG4519cYuLyXuUVh0A";
            var credentials = new SimpleCredentialProvider("00000000-0000-0000-0000-000000000000", "");

            await Assert.ThrowsAsync <UnauthorizedAccessException>(
                async() => await JwtTokenValidation.ValidateAuthHeader(header, credentials, ""));
        }
        public async void EmptyHeader_BotWithNoCredentials_ShouldValidate()
        {
            var header      = "";
            var credentials = new SimpleCredentialProvider("", "");
            var result      = await JwtTokenValidation.ValidateAuthHeader(header, credentials, "");

            Assert.True(result.IsAuthenticated);
        }
        public async void Connector_AuthHeader_BotAppIdDiffers_ShouldNotValidate()
        {
            var header      = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkdDeEFyWG9OOFNxbzdQd2VBNy16NjVkZW5KUSIsIng1dCI6IkdDeEFyWG9OOFNxbzdQd2VBNy16NjVkZW5KUSJ9.eyJzZXJ2aWNldXJsIjoiaHR0cHM6Ly93ZWJjaGF0LmJvdGZyYW1ld29yay5jb20vIiwiaXNzIjoiaHR0cHM6Ly9hcGkuYm90ZnJhbWV3b3JrLmNvbSIsImF1ZCI6IjM5NjE5YTU5LTVhMGMtNGY5Yi04N2M1LTgxNmM2NDhmZjM1NyIsImV4cCI6MTUxNjczNzUyMCwibmJmIjoxNTE2NzM2OTIwfQ.TBgpxbDS-gx1wm7ldvl7To-igfskccNhp-rU1mxUMtGaDjnsU--usH4OXZfzRsZqMlnXWXug_Hgd_qOr5RH8wVlnXnMWewoZTSGZrfp8GOd7jHF13Gz3F1GCl8akc3jeK0Ppc8R_uInpuUKa0SopY0lwpDclCmvDlz4PN6yahHkt_666k-9UGmRt0DDkxuYjbuYG8EDZxyyAhr7J6sFh3yE2UGRpJjRDB4wXWqv08Cp0Gn9PAW2NxOyN8irFzZH5_YZqE3DXDAYZ_IOLpygXQR0O-bFIhLDVxSz6uCeTBRjh8GU7XJ_yNiRDoaby7Rd2IfRrSnvMkBRsB8MsWN8oXg";
            var credentials = new SimpleCredentialProvider("00000000-0000-0000-0000-000000000000", "");

            await Assert.ThrowsAsync <UnauthorizedAccessException>(
                async() => await JwtTokenValidation.ValidateAuthHeader(header, credentials, "https://webchat.botframework.com/"));
        }
        public async void Connector_AuthHeader_CorrectAppIdAndServiceUrl_ShouldValidate()
        {
            var header      = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IkdDeEFyWG9OOFNxbzdQd2VBNy16NjVkZW5KUSIsIng1dCI6IkdDeEFyWG9OOFNxbzdQd2VBNy16NjVkZW5KUSJ9.eyJzZXJ2aWNldXJsIjoiaHR0cHM6Ly93ZWJjaGF0LmJvdGZyYW1ld29yay5jb20vIiwiaXNzIjoiaHR0cHM6Ly9hcGkuYm90ZnJhbWV3b3JrLmNvbSIsImF1ZCI6IjM5NjE5YTU5LTVhMGMtNGY5Yi04N2M1LTgxNmM2NDhmZjM1NyIsImV4cCI6MTUxNjczNzUyMCwibmJmIjoxNTE2NzM2OTIwfQ.TBgpxbDS-gx1wm7ldvl7To-igfskccNhp-rU1mxUMtGaDjnsU--usH4OXZfzRsZqMlnXWXug_Hgd_qOr5RH8wVlnXnMWewoZTSGZrfp8GOd7jHF13Gz3F1GCl8akc3jeK0Ppc8R_uInpuUKa0SopY0lwpDclCmvDlz4PN6yahHkt_666k-9UGmRt0DDkxuYjbuYG8EDZxyyAhr7J6sFh3yE2UGRpJjRDB4wXWqv08Cp0Gn9PAW2NxOyN8irFzZH5_YZqE3DXDAYZ_IOLpygXQR0O-bFIhLDVxSz6uCeTBRjh8GU7XJ_yNiRDoaby7Rd2IfRrSnvMkBRsB8MsWN8oXg";
            var credentials = new SimpleCredentialProvider("39619a59-5a0c-4f9b-87c5-816c648ff357", "");
            var result      = await JwtTokenValidation.ValidateAuthHeader(header, credentials, client);

            Assert.True(result.IsAuthenticated);
        }
        public async void Emulator_MsaHeader_CorrectAppIdAndServiceUrl_ShouldValidate()
        {
            string header      = $"Bearer {await new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F").GetTokenAsync()}";
            var    credentials = new SimpleCredentialProvider("2cd87869-38a0-4182-9251-d056e8f0ac24", "");
            var    result      = await JwtTokenValidation.ValidateAuthHeader(header, credentials, "", "https://webchat.botframework.com/", emptyClient);

            Assert.True(result.IsAuthenticated);
        }
        private async Task JwtTokenValidation_ValidateAuthHeader_WithChannelService_Succeeds(string header, string appId, string pwd, string channelService)
        {
            var credentials = new SimpleCredentialProvider(appId, pwd);
            var channel     = new SimpleChannelProvider(channelService);
            var result      = await JwtTokenValidation.ValidateAuthHeader(header, credentials, channel, string.Empty, "https://webchat.botframework.com/", client);

            Assert.True(result.IsAuthenticated);
        }
        public async void EmptyHeader_BotWithNoCredentials_ShouldThrow()
        {
            var header      = string.Empty;
            var credentials = new SimpleCredentialProvider(string.Empty, string.Empty);

            await Assert.ThrowsAsync <ArgumentNullException>(
                async() => await JwtTokenValidation.ValidateAuthHeader(header, credentials, new SimpleChannelProvider(), string.Empty, null, emptyClient));
        }
        public async void Connector_AuthHeader_BotWithNoCredentials_ShouldNotValidate()
        {
            // token received and auth disabled
            string header      = $"Bearer {await new MicrosoftAppCredentials("2cd87869-38a0-4182-9251-d056e8f0ac24", "2.30Vs3VQLKt974F").GetTokenAsync()}";
            var    credentials = new SimpleCredentialProvider("", "");

            await Assert.ThrowsAsync <UnauthorizedAccessException>(
                async() => await JwtTokenValidation.ValidateAuthHeader(header, credentials, "", null, client));
        }
        private async Task JwtTokenValidation_ValidateAuthHeader_WithChannelService_Throws(string header, string appId, string pwd, string channelService)
        {
            var credentials = new SimpleCredentialProvider(appId, pwd);
            var channel     = new SimpleChannelProvider(channelService);

            await Assert.ThrowsAsync <UnauthorizedAccessException>(
                async() => await JwtTokenValidation.ValidateAuthHeader(
                    header,
                    credentials,
                    channel,
                    string.Empty,
                    "https://webchat.botframework.com/",
                    client));
        }
        /// <summary>
        /// Validates the auth header for WebSocket upgrade requests.
        /// </summary>
        /// <remarks>
        /// Returns a ClaimsIdentity for successful auth and when auth is disabled. Returns null for failed auth.
        /// </remarks>
        /// <param name="httpRequest">The connection request.</param>
        private async Task <ClaimsIdentity> AuthenticateRequestAsync(HttpRequest httpRequest)
        {
            try
            {
                if (!await CredentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
                {
                    var authHeader = httpRequest.Headers.First(x => string.Equals(x.Key, AuthHeaderName, StringComparison.OrdinalIgnoreCase)).Value.FirstOrDefault();
                    var channelId  = httpRequest.Headers.First(x => string.Equals(x.Key, ChannelIdHeaderName, StringComparison.OrdinalIgnoreCase)).Value.FirstOrDefault();

                    if (string.IsNullOrWhiteSpace(authHeader))
                    {
                        await WriteUnauthorizedResponseAsync(AuthHeaderName, httpRequest).ConfigureAwait(false);

                        return(null);
                    }

                    if (string.IsNullOrWhiteSpace(channelId))
                    {
                        await WriteUnauthorizedResponseAsync(ChannelIdHeaderName, httpRequest).ConfigureAwait(false);

                        return(null);
                    }

                    var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, CredentialProvider, ChannelProvider, channelId).ConfigureAwait(false);

                    if (!claimsIdentity.IsAuthenticated)
                    {
                        httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                        return(null);
                    }

                    // Add ServiceURL to the cache of trusted sites in order to allow token refreshing.
                    AppCredentials.TrustServiceUrl(claimsIdentity.FindFirst(AuthenticationConstants.ServiceUrlClaim).Value);
                    ClaimsIdentity = claimsIdentity;
                    return(claimsIdentity);
                }

                // Authentication is not enabled, therefore return an anonymous ClaimsIdentity.
                return(new ClaimsIdentity(new List <Claim>(), "anonymous"));
            }
            catch (Exception)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                await httpRequest.HttpContext.Response.WriteAsync("Error while attempting to authorize connection.").ConfigureAwait(false);

                throw;
            }
        }
Exemplo n.º 14
0
        private async Task <bool> AuthenticateRequestAsync(HttpRequest httpRequest)
        {
            try
            {
                if (!await CredentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
                {
                    var authHeader = httpRequest.Headers.First(x => x.Key.ToLower() == AuthHeaderName).Value.FirstOrDefault();
                    var channelId  = httpRequest.Headers.First(x => x.Key.ToLower() == ChannelIdHeaderName).Value.FirstOrDefault();

                    if (string.IsNullOrWhiteSpace(authHeader))
                    {
                        await WriteUnauthorizedResponseAsync(AuthHeaderName, httpRequest).ConfigureAwait(false);

                        return(false);
                    }

                    if (string.IsNullOrWhiteSpace(channelId))
                    {
                        await WriteUnauthorizedResponseAsync(ChannelIdHeaderName, httpRequest).ConfigureAwait(false);

                        return(false);
                    }

                    var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, CredentialProvider, ChannelProvider, channelId).ConfigureAwait(false);

                    if (!claimsIdentity.IsAuthenticated)
                    {
                        httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                        return(false);
                    }

                    // Add ServiceURL to the cache of trusted sites in order to allow token refreshing.
                    AppCredentials.TrustServiceUrl(claimsIdentity.FindFirst(AuthenticationConstants.ServiceUrlClaim).Value);
                    ClaimsIdentity = claimsIdentity;
                }

                return(true);
            }
            catch (Exception ex)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                await httpRequest.HttpContext.Response.WriteAsync("Error while attempting to authorize connection.").ConfigureAwait(false);

                throw ex;
            }
        }
Exemplo n.º 15
0
        public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (bot == null)
            {
                throw new ArgumentNullException(nameof(bot));
            }

            var authHeader = httpRequest.Headers["Authorization"];
            var channelId  = httpRequest.Headers["ChannelId"];

            try
            {
                var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialProvider, _channelProvider, channelId).ConfigureAwait(false);

                if (!claimsIdentity.IsAuthenticated)
                {
                    httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                    return;
                }
            }
            catch (Exception)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                return;
            }

            if (!httpRequest.HttpContext.WebSockets.IsWebSocketRequest)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                await httpRequest.HttpContext.Response.WriteAsync("Upgrade to WebSocket required.").ConfigureAwait(false);

                return;
            }

            await CreateWebSocketConnectionAsync(httpRequest.HttpContext, authHeader, channelId, bot).ConfigureAwait(false);
        }
Exemplo n.º 16
0
        private async Task <bool> AuthenticateRequestAsync(HttpRequestMessage httpRequest, HttpResponseMessage httpResponse)
        {
            try
            {
                if (!await CredentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
                {
#pragma warning disable CA1308 // Normalize strings to uppercase (header names come in lowercase, ignoring)
                    var authHeader = httpRequest.Headers.GetValues(AuthHeaderName.ToLowerInvariant()).FirstOrDefault();
                    var channelId  = httpRequest.Headers.GetValues(ChannelIdHeaderName.ToLowerInvariant()).FirstOrDefault();
#pragma warning restore CA1308 // Normalize strings to uppercase

                    if (string.IsNullOrWhiteSpace(authHeader))
                    {
                        WriteUnauthorizedResponse(AuthHeaderName, httpResponse);
                        return(false);
                    }

                    if (string.IsNullOrWhiteSpace(channelId))
                    {
                        WriteUnauthorizedResponse(ChannelIdHeaderName, httpResponse);
                        return(false);
                    }

                    var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, CredentialProvider, ChannelProvider, channelId).ConfigureAwait(false);

                    if (!claimsIdentity.IsAuthenticated)
                    {
                        httpResponse.StatusCode = HttpStatusCode.Unauthorized;
                        return(false);
                    }

                    // Add ServiceURL to the cache of trusted sites in order to allow token refreshing.
                    AppCredentials.TrustServiceUrl(claimsIdentity.FindFirst(AuthenticationConstants.ServiceUrlClaim).Value);
                    ClaimsIdentity = claimsIdentity;
                }

                return(true);
            }
            catch (Exception)
            {
                httpResponse.StatusCode = HttpStatusCode.InternalServerError;
                httpResponse.Content    = new StringContent("Error while attempting to authorize connection.");
                throw;
            }
        }
        public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default)
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (bot == null)
            {
                throw new ArgumentNullException(nameof(bot));
            }

            object result     = null;
            var    statusCode = (int)HttpStatusCode.OK;

            try
            {
                // grab the auth header from the inbound http request
                var authHeader     = httpRequest.Headers["Authorization"];
                var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialsProvider, _channelProvider, "unknown").ConfigureAwait(false);

                var route = GetRoute(httpRequest);
                if (route == null)
                {
                    httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                    return;
                }

                // Execute the route action
                result = await route.Action.Invoke(_skillAdapter, bot, claimsIdentity, httpRequest, route.Parameters, cancellationToken).ConfigureAwait(false);
            }
            catch (UnauthorizedAccessException)
            {
                // handle unauthorized here as this layer creates the http response
                statusCode = (int)HttpStatusCode.Unauthorized;
            }

            HttpHelper.WriteResponse(httpResponse, statusCode, result);
        }
Exemplo n.º 18
0
        private async Task <ClaimsIdentity> AuthenticateAsync(string authHeader)
        {
            if (string.IsNullOrWhiteSpace(authHeader))
            {
                var isAuthDisabled = await _credentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false);

                if (isAuthDisabled)
                {
                    // In the scenario where auth is disabled, we still want to have the
                    // IsAuthenticated flag set in the ClaimsIdentity. To do this requires
                    // adding in an empty claim.
                    return(new ClaimsIdentity(new List <Claim>(), "anonymous"));
                }

                // No auth header. Auth is required. Request is not authorized.
                throw new UnauthorizedAccessException();
            }

            return(await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialProvider, _channelProvider, "unknown", _authConfiguration).ConfigureAwait(false));
        }
        private async Task <bool> AuthenticateRequestAsync(HttpRequestMessage httpRequest, HttpResponseMessage httpResponse)
        {
            try
            {
                if (!await CredentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
                {
                    var authHeader = httpRequest.Headers.GetValues(AuthHeaderName.ToLowerInvariant()).FirstOrDefault();
                    var channelId  = httpRequest.Headers.GetValues(ChannelIdHeaderName.ToLowerInvariant()).FirstOrDefault();

                    if (string.IsNullOrWhiteSpace(authHeader))
                    {
                        WriteUnauthorizedResponse(AuthHeaderName, httpResponse);
                        return(false);
                    }

                    if (string.IsNullOrWhiteSpace(channelId))
                    {
                        WriteUnauthorizedResponse(ChannelIdHeaderName, httpResponse);
                        return(false);
                    }

                    var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, CredentialProvider, ChannelProvider, channelId).ConfigureAwait(false);

                    if (!claimsIdentity.IsAuthenticated)
                    {
                        httpResponse.StatusCode = HttpStatusCode.Unauthorized;
                        return(false);
                    }

                    ClaimsIdentity = claimsIdentity;
                }

                return(true);
            }
            catch (Exception)
            {
                httpResponse.StatusCode = HttpStatusCode.InternalServerError;
                httpResponse.Content    = new StringContent("Error while attempting to authorize connection.");
                throw;
            }
        }
        /// <summary>
        /// Helper to authenticate the header.
        /// </summary>
        /// <remarks>
        /// This code is very similar to the code in <see cref="JwtTokenValidation.AuthenticateRequest(IActivity, string, ICredentialProvider, IChannelProvider, AuthenticationConfiguration, HttpClient)"/>,
        /// we should move this code somewhere in that library when we refactor auth, for now we keep it private to avoid adding more public static
        /// functions that we will need to deprecate later.
        /// </remarks>
        /// <param name="authHeader">The auth header containing JWT token.</param>
        /// <param name="cancellationToken">A cancellation token.</param>
        /// <returns>A <see cref="ClaimsIdentity"/> representing the claims associated with given header.</returns>
        internal override async Task <ClaimsIdentity> AuthenticateAsync(string authHeader, CancellationToken cancellationToken)
        {
            if (string.IsNullOrWhiteSpace(authHeader))
            {
                var isAuthDisabled = await _credentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false);

                if (!isAuthDisabled)
                {
                    // No auth header. Auth is required. Request is not authorized.
                    throw new UnauthorizedAccessException();
                }

                // In the scenario where auth is disabled, we still want to have the
                // IsAuthenticated flag set in the ClaimsIdentity.
                // To do this requires adding in an empty claim.
                // Since ChannelServiceHandler calls are always a skill callback call, we set the skill claim too.
                return(SkillValidation.CreateAnonymousSkillClaim());
            }

            // Validate the header and extract claims.
            return(await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialProvider, ChannelProvider, "unknown", _authConfiguration).ConfigureAwait(false));
        }
        /// <summary>
        /// Process the initial request to establish a long lived connection via a streaming server.
        /// </summary>
        /// <param name="onTurnError"> The function to execute on turn errors.</param>
        /// <param name="middlewareSet">The set of middleware to perform on each turn.</param>
        /// <param name="httpRequest">The connection request.</param>
        /// <param name="httpResponse">The response sent on error or connection termination.</param>
        /// <param name="cancellationToken">Optional cancellation token.</param>
        /// <returns>Returns on task completion.</returns>
        internal async Task ProcessAsync(Func <ITurnContext, Exception, Task> onTurnError, List <Builder.IMiddleware> middlewareSet, HttpRequest httpRequest, HttpResponse httpResponse, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (!httpRequest.HttpContext.WebSockets.IsWebSocketRequest)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                await httpRequest.HttpContext.Response.WriteAsync("Upgrade to WebSocket is required.").ConfigureAwait(false);

                return;
            }

            try
            {
                if (!await _credentialProvider.IsAuthenticationDisabledAsync().ConfigureAwait(false))
                {
                    var authHeader = httpRequest.Headers.Where(x => x.Key.ToLower() == AuthHeaderName).FirstOrDefault().Value.FirstOrDefault();
                    var channelId  = httpRequest.Headers.Where(x => x.Key.ToLower() == ChannelIdHeaderName).FirstOrDefault().Value.FirstOrDefault();

                    if (string.IsNullOrWhiteSpace(authHeader))
                    {
                        await MissingAuthHeaderHelperAsync(AuthHeaderName, httpRequest).ConfigureAwait(false);

                        return;
                    }

                    if (string.IsNullOrWhiteSpace(channelId))
                    {
                        await MissingAuthHeaderHelperAsync(ChannelIdHeaderName, httpRequest).ConfigureAwait(false);

                        return;
                    }

                    var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialProvider, _channelProvider, channelId).ConfigureAwait(false);

                    if (!claimsIdentity.IsAuthenticated)
                    {
                        httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;

                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                httpRequest.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                await httpRequest.HttpContext.Response.WriteAsync("Error while attempting to authorize connection.").ConfigureAwait(false);

                throw ex;
            }

            await CreateStreamingServerConnectionAsync(onTurnError, middlewareSet, httpRequest.HttpContext).ConfigureAwait(false);
        }
Exemplo n.º 22
0
 private async Task <ClaimsIdentity> AuthenticateAsync(string authHeader)
 {
     return(await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialProvider, _channelProvider, "unknown", _authConfiguration).ConfigureAwait(false));
 }
        public async Task ProcessAsync(HttpRequest httpRequest, HttpResponse httpResponse, IBot bot, CancellationToken cancellationToken = default)
        {
            if (httpRequest == null)
            {
                throw new ArgumentNullException(nameof(httpRequest));
            }

            if (httpResponse == null)
            {
                throw new ArgumentNullException(nameof(httpResponse));
            }

            if (bot == null)
            {
                throw new ArgumentNullException(nameof(bot));
            }

            var route = GetRoute(httpRequest);

            if (route == null)
            {
                httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                return;
            }

            object result     = null;
            var    statusCode = (int)HttpStatusCode.OK;

            try
            {
                // grab the auth header from the inbound http request
                var authHeader     = httpRequest.Headers["Authorization"];
                var claimsIdentity = await JwtTokenValidation.ValidateAuthHeader(authHeader, _credentialsProvider, _channelProvider, "unknown").ConfigureAwait(false);

                switch (route.Method)
                {
                // [Route("/v3/conversations")]
                case ChannelApiMethods.CreateConversation:
                    var parameters = HttpHelper.ReadRequest <ConversationParameters>(httpRequest);
                    result = await _skillAdapter.CreateConversationAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, parameters, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities/{activityId}")]
                case ChannelApiMethods.DeleteActivity:
                    // TODO: ask Tom why we use the value from the route and not from the activity here.
                    await _skillAdapter.DeleteActivityAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, route.Parameters["activityId"].Value, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/members/{memberId}")]
                case ChannelApiMethods.DeleteConversationMember:
                    await _skillAdapter.DeleteConversationMemberAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, route.Parameters["memberId"].Value, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities/{activityId}/members")]
                case ChannelApiMethods.GetActivityMembers:
                    result = await _skillAdapter.GetActivityMembersAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, route.Parameters["activityId"].Value, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/members")]
                case ChannelApiMethods.GetConversationMembers:
                    result = await _skillAdapter.GetConversationMembersAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/pagedmembers")]
                case ChannelApiMethods.GetConversationPagedMembers:
                    var pageSize = string.IsNullOrWhiteSpace(route.Parameters["pageSize"].Value) ? -1 : int.Parse(route.Parameters["pageSize"].Value, CultureInfo.InvariantCulture);
                    result = await _skillAdapter.GetConversationPagedMembersAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, pageSize, route.Parameters["continuationToken"].Value, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations")]
                case ChannelApiMethods.GetConversations:
                    result = await _skillAdapter.GetConversationsAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, cancellationToken : cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities/{activityId}")]
                case ChannelApiMethods.ReplyToActivity:
                    var replyToActivity = HttpHelper.ReadRequest <Activity>(httpRequest);
                    result = await _skillAdapter.ReplyToActivityAsync(bot, claimsIdentity, replyToActivity.Conversation.Id, route.Parameters["activityId"].Value, replyToActivity, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities/history")]
                case ChannelApiMethods.SendConversationHistory:
                    var history = HttpHelper.ReadRequest <Transcript>(httpRequest);
                    result = await _skillAdapter.SendConversationHistoryAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, history, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities")]
                case ChannelApiMethods.SendToConversation:
                    var sendToConversationActivity = HttpHelper.ReadRequest <Activity>(httpRequest);
                    result = await _skillAdapter.SendToConversationAsync(bot, claimsIdentity, sendToConversationActivity.Conversation.Id, sendToConversationActivity, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/activities/{activityId}")]
                case ChannelApiMethods.UpdateActivity:
                    var updateActivity = HttpHelper.ReadRequest <Activity>(httpRequest);
                    result = await _skillAdapter.UpdateActivityAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, route.Parameters["activityId"].Value, updateActivity, cancellationToken).ConfigureAwait(false);

                    break;

                // [Route("/v3/conversations/{conversationId}/attachments")]
                case ChannelApiMethods.UploadAttachment:
                    var uploadAttachment = HttpHelper.ReadRequest <AttachmentData>(httpRequest);
                    result = await _skillAdapter.UploadAttachmentAsync(bot, claimsIdentity, route.Parameters["conversationId"].Value, uploadAttachment, cancellationToken).ConfigureAwait(false);

                    break;

                default:
                    httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
                    return;
                }
            }
            catch (UnauthorizedAccessException)
            {
                // handle unauthorized here as this layer creates the http response
                statusCode = (int)HttpStatusCode.Unauthorized;
            }

            HttpHelper.WriteResponse(httpResponse, statusCode, result);
        }