Esempio n. 1
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.TryGetValue("Authorization", out var headerValue))
            {
                Logger.LogInformation("Missing authorization header.");
                return(AuthenticateResult.Fail("Missing authorization header."));
            }

            if (!AuthenticationHeaderValue.TryParse(headerValue, out var authHeader))
            {
                Logger.LogInformation("Invalid authorization header.");
                return(AuthenticateResult.Fail("Invalid authorization header."));
            }

            var jwt = authHeader.ToString().Replace("Bearer ", "").Trim();

            if (!_jwtService.TryDecode(jwt, out var decodedClaims))
            {
                return(AuthenticateResult.Fail("Invalid jwt token"));
            }

            if (!decodedClaims.ContainsKey("id") || !decodedClaims.ContainsKey("access_token") || !await _jwtClaimValidator.ValidateAsync(decodedClaims))
            {
                return(AuthenticateResult.Fail("Invalid jwt token"));
            }

            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, decodedClaims["id"]),
                new Claim(TheIdentityHubClaimTypes.AccessToken, decodedClaims["access_token"]),
            };

            var identity  = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
Esempio n. 2
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!_httpContextAccessor.HttpContext.Request.Headers.ContainsKey(AuthorizationHeaderName))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!AuthenticationHeaderValue.TryParse(Request.Headers[AuthorizationHeaderName], out AuthenticationHeaderValue headerValue))
            {
                return(AuthenticateResult.NoResult());
            }

            if (headerValue.Scheme != OpaqueTokenDefaults.AuthenticationScheme)
            {
                return(AuthenticateResult.NoResult());
            }

            var tokenText = headerValue.Parameter;
            var token     = await _context.AccessTokens.Include(at => at.User).FirstOrDefaultAsync(at => at.Id == tokenText);

            if (token == null || token.Created.AddSeconds(token.Ttl) < DateTime.UtcNow)
            {
                return(AuthenticateResult.NoResult());
            }

            var claims = new []
            {
                new Claim(ClaimTypes.Name, token.User.Username),
                new Claim(CustomClaimTypes.TokenId, token.Id),
                new Claim(ClaimTypes.Role, "ExampleRole"),
            };

            var identity  = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
        protected async override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey("Authorization"))
            {
                return(AuthenticateResult.NoResult());
            }
            if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue headerValue))
            {
                return(AuthenticateResult.NoResult());
            }
            if (!"Bearer".Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                return(AuthenticateResult.NoResult());
            }
            var idToken   = headerValue.Parameter;
            var principal = await this.googleAccountService.CreateUserFromIdToken(idToken, this.Scheme.Name);

            if (principal == null)
            {
                return(AuthenticateResult.Fail("Invalid google identity token"));
            }
            return(AuthenticateResult.Success(new AuthenticationTicket(principal, Scheme.Name)));
        }
Esempio n. 4
0
        /// <summary>
        /// Handle authentication
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out var authenticationHeaderValue))
            {
                var(name, pass) = authenticationHeaderValue.Parameter.AuthorizationParameterToBasicAuth();

                if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pass))
                {
                    return(AuthenticateResult.NoResult());
                }

                var userAuthInfo = await UserManager.AuthenticateAsync(name, pass);

                if (userAuthInfo == null)
                {
                    return(AuthenticateResult.Fail($"Name={name} is not found."));
                }

                var identity = new ClaimsIdentity(userAuthInfo.Select(x => new Claim(x.Key, x.Value)), BasicAuthenticationConstants.Basic);
                return(AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(identity), BasicAuthenticationConstants.Basic)));
            }
            return(AuthenticateResult.NoResult());
        }
Esempio n. 5
0
        /// <summary>Authentication behavior.</summary>
        /// <returns>The <see cref="T:Microsoft.AspNetCore.Authentication.AuthenticateResult" /> result.</returns>
        public async Task <AuthenticateResult> AuthenticateAsync()
        {
            var authHeader = this.context.Request.Headers["Authorization"];

            if (AuthenticationHeaderValue.TryParse(authHeader, out var authValue))
            {
                if (authValue.Scheme.Equals("token", StringComparison.InvariantCultureIgnoreCase))
                {
                    var token = authValue.Parameter;
                    return(await this.UserTokenVerify(token));
                }

                throw new ApplicationException("unsupport");
            }
            else if (this.context.Request.Cookies.TryGetValue("token", out string token))
            {
                return(await this.UserTokenVerify(token));
            }
            else
            {
                return(AuthenticateResult.Fail("need token"));
            }
        }
Esempio n. 6
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey("Authorization"))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue headerValue))
            {
                return(AuthenticateResult.NoResult());
            }

            if (headerValue.Scheme != Options.Scheme)
            {
                return(AuthenticateResult.NoResult());
            }

            var apiKey = headerValue.Parameter;

            var application = _applicationsRepository.GetByApiKey(apiKey);

            if (application != null)
            {
                var claims = new List <Claim>()
                {
                    new Claim("Name", application.Name),
                };

                var identity  = new ClaimsIdentity(claims, Options.AuthenticationType);
                var principle = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principle, Options.Scheme);

                return(AuthenticateResult.Success(ticket));
            }

            return(AuthenticateResult.Fail("Invalid api key"));
        }
Esempio n. 7
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey(AuthorizationHeaderName))
            {
                //Authorization header not in request
                return(AuthenticateResult.NoResult());
            }

            if (!AuthenticationHeaderValue.TryParse(Request.Headers[AuthorizationHeaderName], out AuthenticationHeaderValue headerValue))
            {
                //Invalid Authorization header
                return(AuthenticateResult.NoResult());
            }

            if (!Options.Scheme.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                //Not Basic authentication header
                return(AuthenticateResult.NoResult());
            }


            var validUser = await _authenticationService.GetClaimsForKeyAsync(headerValue.Parameter);

            if (validUser == null)
            {
                return(AuthenticateResult.Fail("Invalid key"));
            }
            var claims = new List <Claim>(validUser);

            claims.Add(new Claim(ClaimTypes.Role, Options.Realm));

            var identity  = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
        protected async override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!AuthenticationHeaderValue.TryParse(Request.Headers[HeaderNames.Authorization], out var authValue))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!authValue.Scheme.Equals(Scheme.Name, StringComparison.InvariantCultureIgnoreCase))
            {
                return(AuthenticateResult.NoResult());
            }

            var credentials = Encoding.UTF8.GetString(Convert.FromBase64String(authValue.Parameter ?? string.Empty))
                              .Split(':', 2);

            if (credentials.Length != 2)
            {
                return(AuthenticateResult.Fail("Basic token is malformed"));
            }

            var user = await signInManager.UserManager.FindByNameAsync(credentials[0]);

            if (user is null)
            {
                return(AuthenticateResult.Fail("Username or password is incorrect"));
            }

            if (!await signInManager.UserManager.CheckPasswordAsync(user, credentials[1]))
            {
                return(AuthenticateResult.Fail("Username or password is incorrect"));
            }

            var ticket = new AuthenticationTicket(await signInManager.ClaimsFactory.CreateAsync(user), Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
        /// <summary>
        /// Return user object from a valid token. This method only checks the local Token Cache.
        /// </summary>
        /// <param name="request"></param>
        /// <returns>User object</returns>
        /// <exception cref="TokenDoesNotExistException"></exception>
        public async Task <User> GetUserFromValidToken(HttpRequest request)
        {
            var    authorization = request.Headers[HeaderNames.Authorization];
            string token         = null;

            if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
            {
                var scheme = headerValue.Scheme;
                token = headerValue.Parameter;
            }

            TokenCache cachedToken = CheckForValidTokenByToken(token);

            bool tokenValid = cachedToken != null;

            if (tokenValid)
            {
                return(cachedToken.User);
            }
            else
            {
                throw new TokenDoesNotExistException();
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            Request.Headers.TryGetValue("Authorization", out var authHeader);
            AuthenticationHeaderValue.TryParse(authHeader, out var authHeaderValue);
            if (string.IsNullOrEmpty(authHeaderValue?.Parameter))
            {
                return(AuthenticateResult.Fail("Authorization header not provided"));
            }

            byte[] data        = Convert.FromBase64String(authHeaderValue?.Parameter);
            string credentials = Encoding.UTF8.GetString(data);
            var    split       = credentials.Split(':', 2);

            if (split.Count() != 2)
            {
                return(AuthenticateResult.Fail("Invalid Authorization Header"));
            }

            var clientId     = split[0];
            var clientSecret = split[1];

            if (clientId != "noxton" || clientSecret != "XcYcnx-=wb9;WP*V")
            {
                return(AuthenticateResult.Fail("Invalid Authorization Header"));
            }

            var claims = new[] {
                new Claim(ClaimTypes.NameIdentifier, "tesst")
            };

            var identity  = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
 public async Task <IActionResult> logout()
 {
     try
     {
         var authorization = Request.Headers[HeaderNames.Authorization];
         if (AuthenticationHeaderValue.TryParse(authorization, out var headerValue))
         {
             var jwt = headerValue.Parameter;
             await _userservice.logout(jwt);
         }
         return(Ok());
     }
     catch (Exception e)
     {
         if (e.Message.Length > 0)
         {
             return(BadRequest(e.Message));
         }
         else
         {
             throw;
         }
     }
 }
Esempio n. 12
0
        protected override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            // Get Authorization header value
            if (!AuthenticationHeaderValue.TryParse(Request.Headers[AuthorizationHeaderName], out AuthenticationHeaderValue headerValue))
            {
                //Invalid Authorization header
                return(Task.FromResult(AuthenticateResult.Fail("Cannot read authorization header.")));
            }
            var header = headerValue.Scheme;
            var valueh = headerValue.Parameter;

            if (!BasicSchemeName.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                //Not Basic authentication header
                return(Task.FromResult(AuthenticateResult.Fail("Cannot read authorization sehema.")));
            }

            var identities = new List <ClaimsIdentity> {
                new ClaimsIdentity("custom auth type")
            };
            var ticket = new AuthenticationTicket(new ClaimsPrincipal(identities), Options.Scheme);

            return(Task.FromResult(AuthenticateResult.Success(ticket)));
        }
        public string GetAgeToken()
        {
            string token = HttpContext.Request.Headers["Authorization"];

            if (AuthenticationHeaderValue.TryParse(token, out var headerValue))
            {
                // we have a valid AuthenticationHeaderValue that has the following details:

                var scheme    = headerValue.Scheme;
                var parameter = headerValue.Parameter;

                // scheme will be "Bearer"
                // parmameter will be the token itself.
                var    stream    = parameter;
                var    handler   = new JwtSecurityTokenHandler();
                var    jsonToken = handler.ReadToken(stream);
                var    tokenS    = jsonToken as JwtSecurityToken;
                var    jti       = tokenS.Claims.First(claim => claim.Type == "Age").Value;
                string word      = "The Age is : ";
                var    result    = word + jti;
                return(result);
            }
            return("Error");
        }
Esempio n. 14
0
        // Helpers

        private async Task <AuthGUID> GetGUIDAsync(HttpRequest req)
        {
            AuthGUID        authGUID   = new AuthGUID();
            AuthResultModel authResult = new AuthResultModel(false, AuthStatusCode.Unauthorized);

            // Get AuthentificationHeader from request
            AuthenticationHeaderValue.TryParse(req.Headers[HeaderNames.Authorization], out var authHeader);

            if (authHeader == null)
            {
                return new AuthGUID {
                           AuthResult = authResult
                }
            }
            ;

            // Token validation with Auth0 servers
            ClaimsPrincipal claims = await Auth0.ValidateTokenAsync(authHeader);

            if (claims == null)
            {
                return new AuthGUID {
                           AuthResult = authResult
                }
            }
            ;

            // Get Token Guid for Authorization
            string tokenGuid = claims.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value;

            authGUID.Acces      = true;
            authGUID.GUID       = tokenGuid;
            authGUID.AuthResult = new AuthResultModel(true, AuthStatusCode.Ok);
            return(authGUID);
        }
    }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out AuthenticationHeaderValue authHeader))
            {
                try
                {
                    if (string.IsNullOrEmpty(authHeader?.Parameter) || !authHeader.Scheme.Equals("Bearer", StringComparison.OrdinalIgnoreCase))
                    {
                        return(AuthenticateResult.Fail("Invalid Authorization Header"));
                    }

                    var jwtTokenString = authHeader.Parameter;
                    var token          = _tokenService.Read(jwtTokenString);

                    var account = await _accountService.GetByUsernameAsync(GetEmailFromClaims(token.Claims));

                    if (account == null)
                    {
                        return(AuthenticateResult.Fail("User not found"));
                    }

                    var principal = _tokenService.Validate(jwtTokenString);
                    if (principal == null)
                    {
                        return(AuthenticateResult.Fail("Token validation failed"));
                    }

                    return(AuthenticateResult.Success(new AuthenticationTicket(principal, Scheme.Name)));
                }
                catch (Exception ex)
                {
                    return(AuthenticateResult.Fail(ex.Message));
                }
            }
            return(AuthenticateResult.Fail("Missing Authorization Header"));
        }
Esempio n. 16
0
        public static async Task <IActionResult> CreateExperience(
            [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "experience")] HttpRequest req,
            [Table("aramizexperience", Connection = "AzureWebJobsStorage")] IAsyncCollector <ExperienceEntity> exeperinceTable,
            ILogger log)
        {
            log.LogInformation("Creating new aramiz experience entity");

            ClaimsPrincipal principal;

            AuthenticationHeaderValue.TryParse(req.Headers[HeaderNames.Authorization], out var authHeader);
            if ((principal = await Security.ValidateTokenAsync(authHeader)) == null)
            {
                return(new UnauthorizedResult());
            }

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            var    input       = JsonConvert.DeserializeObject <ExperienceCreateModel>(requestBody);

            var experienceEntity = new ExperienceModel
            {
                expEmployeeTitle   = input.expEmployeeTitle,
                expCompanyLogoUri  = input.expCompanyLogoUri,
                expCompany         = input.expCompany,
                expLocation        = input.expLocation,
                expCurrentWorkRole = input.expCurrentWorkRole,
                expStartDate       = input.expStartDate,
                expEndDate         = input.expEndDate,
                expWorkSubject     = input.expWorkSubject,
                expWorkDescription = input.expWorkDescription,
                expWorkLinks       = input.expWorkLinks
            };

            await exeperinceTable.AddAsync(experienceEntity.ExperienceTableEntity());

            return(new OkObjectResult(experienceEntity));
        }
Esempio n. 17
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                // get header
                if (!AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out var authorization) || authorization.Scheme != Scheme.Name)
                {
                    _results.Labels("none").Inc();
                    return(AuthenticateResult.NoResult());
                }

                OneOf <AuthTokenPayload, TokenValidationError> result;

                using (_time.Measure())
                    result = await _auth.ValidateTokenAsync(authorization.Parameter);

                if (!result.TryPickT0(out var payload, out var error))
                {
                    _results.Labels("fail").Inc();
                    return(AuthenticateResult.Fail(error.ToString()));
                }

                // pass payload down the pipeline
                Context.Items[PayloadItemKey] = payload;

                // we don't use asp.net claims, but integrations like Sentry do
                var ticket = new AuthenticationTicket(new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.NameIdentifier, payload.UserId) }, SchemeName)), SchemeName);

                _results.Labels("success").Inc();
                return(AuthenticateResult.Success(ticket));
            }
            catch (Exception e)
            {
                return(AuthenticateResult.Fail($"Authentication failed. {e.Message}"));
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string protectedToken = null;

            if (Request.Headers.TryGetValue("Authorization", out StringValues authHeader) &&
                AuthenticationHeaderValue.TryParse(authHeader.ToString(), out AuthenticationHeaderValue auth) &&
                !string.IsNullOrEmpty(auth.Parameter) &&
                auth.Parameter.Length < 1000)
            {
                switch (auth.Scheme.ToLowerInvariant())
                {
                case "basic":
                    protectedToken = ParseBasicAuth(auth.Parameter);
                    break;

                case "bearer":
                    protectedToken = auth.Parameter;
                    break;
                }
            }

            if (string.IsNullOrEmpty(protectedToken) &&
                Request.Query.TryGetValue("token", out StringValues tokenQuery))
            {
                protectedToken = tokenQuery.ToString();
            }

            if (string.IsNullOrEmpty(protectedToken))
            {
                Logger.LogInformation("No token found in 'Authorization: Bearer <token>', 'Authorization: Basic <base64(ignored:<token>)>', or '?token=<token>'");
                return(AuthenticateResult.NoResult());
            }

            if (!TryDecodeToken(protectedToken, out GitHubTokenData token))
            {
                string reportToken = protectedToken;
                if (reportToken.Length > 10)
                {
                    reportToken = reportToken.Substring(0, 5) + "..." + reportToken.Substring(reportToken.Length - 5);
                }

                Logger.LogWarning("Token failed to decode correctly, token signature... {token}", reportToken);
                return(AuthenticateResult.Fail("Invalid token"));
            }

            if (await _revocation.IsTokenRevokedAsync(token.UserId, token.TokenId))
            {
                Logger.LogWarning("Revoked token used, user {user}, token {token}", token.UserId, token.TokenId);
                return(AuthenticateResult.Fail("Invalid token"));
            }

            (IEnumerable <Claim> userClaims, IEnumerable <Claim> groupClaims) = await Task.WhenAll(
                _resolver.GetUserInformationClaims(token.AccessToken, Context.RequestAborted),
                _resolver.GetMembershipClaims(token.AccessToken, Context.RequestAborted)
                );

            var identity  = new ClaimsIdentity(userClaims.Concat(groupClaims), Scheme.Name);
            var principal = new ClaimsPrincipal(new[] { identity });
            var ticket    = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
Esempio n. 19
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string authHeaderValue = Request.Headers.TryGetAndReturn("Authorization").FirstOrDefault();
            AuthenticationHeaderValue authHeader = null;

            if (!String.IsNullOrEmpty(authHeaderValue) && !AuthenticationHeaderValue.TryParse(authHeaderValue, out authHeader))
            {
                return(AuthenticateResult.Fail("Unable to parse header"));
            }

            string scheme = authHeader?.Scheme.ToLower();
            string token  = null;

            if (authHeader != null && (scheme == BearerScheme || scheme == TokenScheme))
            {
                token = authHeader.Parameter;
            }
            else if (authHeader != null && scheme == BasicScheme)
            {
                var authInfo = Request.GetBasicAuth();
                if (authInfo != null)
                {
                    if (authInfo.Username.ToLower() == "client")
                    {
                        token = authInfo.Password;
                    }
                    else if (authInfo.Password.ToLower() == "x-oauth-basic" || String.IsNullOrEmpty(authInfo.Password))
                    {
                        token = authInfo.Username;
                    }
                    else
                    {
                        User user;
                        try {
                            user = await _userRepository.GetByEmailAddressAsync(authInfo.Username);
                        } catch (Exception ex) {
                            return(AuthenticateResult.Fail(ex));
                        }

                        if (user == null || !user.IsActive)
                        {
                            return(AuthenticateResult.Fail("User is not valid"));
                        }

                        if (String.IsNullOrEmpty(user.Salt))
                        {
                            return(AuthenticateResult.Fail("User is not valid"));
                        }

                        string encodedPassword = authInfo.Password.ToSaltedHash(user.Salt);
                        if (!String.Equals(encodedPassword, user.Password))
                        {
                            return(AuthenticateResult.Fail("User is not valid"));
                        }

                        return(AuthenticateResult.Success(CreateUserAuthenticationTicket(user)));
                    }
                }
            }
            else
            {
                token = Request.GetQueryString("access_token");
                if (String.IsNullOrEmpty(token))
                {
                    token = Request.GetQueryString("api_key");
                }

                if (String.IsNullOrEmpty(token))
                {
                    token = Request.GetQueryString("apikey");
                }
            }

            if (String.IsNullOrEmpty(token))
            {
                return(AuthenticateResult.NoResult());
            }

            var tokenRecord = await _tokenRepository.GetByIdAsync(token, o => o.Cache());

            if (tokenRecord == null)
            {
                using (Logger.BeginScope(new ExceptionlessState().Property("Headers", Request.Headers)))
                    Logger.LogWarning("Token {Token} for {Path} not found.", token, Request.Path);

                return(AuthenticateResult.Fail("Token is not valid"));
            }

            if (tokenRecord.ExpiresUtc.HasValue && tokenRecord.ExpiresUtc.Value < Foundatio.Utility.SystemClock.UtcNow)
            {
                using (Logger.BeginScope(new ExceptionlessState().Property("Headers", Request.Headers)))
                    Logger.LogWarning("Token {Token} for {Path} expired on {TokenExpiresUtc}.", token, Request.Path, tokenRecord.ExpiresUtc.Value);

                return(AuthenticateResult.Fail("Token is not valid"));
            }

            if (!String.IsNullOrEmpty(tokenRecord.UserId))
            {
                var user = await _userRepository.GetByIdAsync(tokenRecord.UserId, o => o.Cache());

                if (user == null)
                {
                    using (Logger.BeginScope(new ExceptionlessState().Property("Headers", Request.Headers)))
                        Logger.LogWarning("Could not find user for token {Token} with user {user} for {Path}.", token, tokenRecord.UserId, Request.Path);

                    return(AuthenticateResult.Fail("Token is not valid"));
                }

                return(AuthenticateResult.Success(CreateUserAuthenticationTicket(user, tokenRecord)));
            }

            return(AuthenticateResult.Success(CreateTokenAuthenticationTicket(tokenRecord)));
        }
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var description = (ControllerActionDescriptor)context.ActionDescriptor;

            //匿名标识
            var allowAnonymous = description.MethodInfo.GetCustomAttribute(typeof(AllowAnonymousAttribute));

            if (allowAnonymous != null)
            {
                return;
            }

            var request = context.HttpContext.Request;

            string method  = request.Method;
            string rawUrl  = request.Path.Value + request.QueryString.Value;
            string date    = request.Headers["Date"];
            string content = null;

            if (request.Body.CanSeek)
            {
                request.Body.Position = 0;
                content = await new StreamReader(request.Body).ReadToEndAsync();
                request.Body.Position = 0;
            }

            if (AuthenticationHeaderValue.TryParse(request.Headers["Authorization"], out AuthenticationHeaderValue authorization))
            {
                if (String.Equals("PKC", authorization.Scheme, StringComparison.CurrentCultureIgnoreCase))
                {
                    string[] split  = authorization.Parameter.Split(':');
                    string   parkID = split[0];
                    string   sign   = split[1];
                    var      parkPO = await new ParkRep <parkPO>().SingleOrDefaultAsync(parkID);
                    if (parkPO != null)
                    {
                        string preString = method + "\n"
                                           + rawUrl + "\n"
                                           + date + "\n"
                                           + content + "\n";

                        string sha1 = Crypto.GetHMACSHA1(preString, parkPO.park_key);
                        if (String.Equals(sign, sha1, StringComparison.CurrentCultureIgnoreCase))
                        {
                            context.HttpContext.Items.Add("ParkUser", parkPO);
                            return;
                        }
                        else
                        {
                            Log.Warn($"{parkID}签名计算不通过");
                        }
                    }
                    else
                    {
                        Log.Warn($"{parkID}应用不存在");
                    }
                }
                else
                {
                    Log.Warn($"Authorization头格式不合法:{request.Headers["Authorization"]}");
                }
            }
            else
            {
                Log.Warn($"Authorization头格式不合法:{request.Headers["Authorization"]}");
            }

            context.Result = new UnauthorizedResult();
        }
Esempio n. 21
0
    public void Configure(
        IApplicationBuilder app,
        IWebHostEnvironment env,
        IHostApplicationLifetime appLifetime,
        Func <DateTimeOffset> getDateTimeOffset,
        FileStoreForProcessStore processStoreForFileStore)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        var configuration = app.ApplicationServices.GetService <IConfiguration>();

        var adminPassword = configuration.GetValue <string>(Configuration.AdminPasswordSettingKey);

        object avoidConcurrencyLock = new();

        var processStoreFileStore = processStoreForFileStore.fileStore;

        PublicHostConfiguration?publicAppHost = null;

        void stopPublicApp()
        {
            lock (avoidConcurrencyLock)
            {
                if (publicAppHost != null)
                {
                    logger.LogInformation("Begin to stop the public app.");

                    publicAppHost?.webHost?.StopAsync(TimeSpan.FromSeconds(10)).Wait();
                    publicAppHost?.webHost?.Dispose();
                    publicAppHost?.processLiveRepresentation?.Dispose();
                    publicAppHost = null;
                }
            }
        }

        appLifetime.ApplicationStopping.Register(() =>
        {
            stopPublicApp();
        });

        var processStoreWriter =
            new ProcessStoreWriterInFileStore(
                processStoreFileStore,
                getTimeForCompositionLogBatch: getDateTimeOffset,
                processStoreFileStore);

        void startPublicApp()
        {
            lock (avoidConcurrencyLock)
            {
                stopPublicApp();

                logger.LogInformation("Begin to build the process live representation.");

                var restoreProcessResult =
                    PersistentProcess.PersistentProcessLiveRepresentation.LoadFromStoreAndRestoreProcess(
                        new ProcessStoreReaderInFileStore(processStoreFileStore),
                        logger: logEntry => logger.LogInformation(logEntry));

                var processLiveRepresentation = restoreProcessResult.process;

                logger.LogInformation("Completed building the process live representation.");

                var            cyclicReductionStoreLock            = new object();
                DateTimeOffset?cyclicReductionStoreLastTime        = null;
                var            cyclicReductionStoreDistanceSeconds = (int)TimeSpan.FromMinutes(10).TotalSeconds;

                void maintainStoreReductions()
                {
                    var currentDateTime = getDateTimeOffset();

                    System.Threading.Thread.MemoryBarrier();
                    var cyclicReductionStoreLastAge = currentDateTime - cyclicReductionStoreLastTime;

                    if (!(cyclicReductionStoreLastAge?.TotalSeconds < cyclicReductionStoreDistanceSeconds))
                    {
                        if (System.Threading.Monitor.TryEnter(cyclicReductionStoreLock))
                        {
                            try
                            {
                                var afterLockCyclicReductionStoreLastAge = currentDateTime - cyclicReductionStoreLastTime;

                                if (afterLockCyclicReductionStoreLastAge?.TotalSeconds < cyclicReductionStoreDistanceSeconds)
                                {
                                    return;
                                }

                                lock (avoidConcurrencyLock)
                                {
                                    var(reductionRecord, _) = processLiveRepresentation.StoreReductionRecordForCurrentState(processStoreWriter !);
                                }

                                cyclicReductionStoreLastTime = currentDateTime;
                                System.Threading.Thread.MemoryBarrier();
                            }
                            finally
                            {
                                System.Threading.Monitor.Exit(cyclicReductionStoreLock);
                            }
                        }
                    }
                }

                IWebHost buildWebHost(
                    PersistentProcess.ProcessAppConfig processAppConfig,
                    IReadOnlyList <string> publicWebHostUrls)
                {
                    var appConfigTree = Composition.ParseAsTreeWithStringPath(processAppConfig.appConfigComponent).Ok !;

                    var appConfigFilesNamesAndContents =
                        appConfigTree.EnumerateBlobsTransitive();

                    var webAppConfigurationFile =
                        appConfigFilesNamesAndContents
                        .FirstOrDefault(filePathAndContent => filePathAndContent.path.SequenceEqual(JsonFilePath))
                        .blobContent;

                    var webAppConfiguration =
                        webAppConfigurationFile == null
                        ?
                        null
                        :
                        System.Text.Json.JsonSerializer.Deserialize <WebAppConfigurationJsonStructure>(Encoding.UTF8.GetString(webAppConfigurationFile.ToArray()));

                    return
                        (Microsoft.AspNetCore.WebHost.CreateDefaultBuilder()
                         .ConfigureLogging((hostingContext, logging) =>
                    {
                        logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                        logging.AddConsole();
                        logging.AddDebug();
                    })
                         .ConfigureKestrel(kestrelOptions =>
                    {
                        kestrelOptions.ConfigureHttpsDefaults(httpsOptions =>
                        {
                            httpsOptions.ServerCertificateSelector = (c, s) => FluffySpoon.AspNet.LetsEncrypt.LetsEncryptRenewalService.Certificate;
                        });
                    })
                         .UseUrls(publicWebHostUrls.ToArray())
                         .UseStartup <StartupPublicApp>()
                         .WithSettingDateTimeOffsetDelegate(getDateTimeOffset)
                         .ConfigureServices(services =>
                    {
                        services.AddSingleton(
                            new WebAppAndElmAppConfig(
                                WebAppConfiguration: webAppConfiguration,
                                ProcessEventInElmApp: serializedEvent =>
                        {
                            lock (avoidConcurrencyLock)
                            {
                                var elmEventResponse =
                                    processLiveRepresentation.ProcessElmAppEvent(
                                        processStoreWriter !, serializedEvent);

                                maintainStoreReductions();

                                return elmEventResponse;
                            }
                        },
                                SourceComposition: processAppConfig.appConfigComponent,
                                InitOrMigrateCmds: restoreProcessResult.initOrMigrateCmds
                                ));
                    })
                         .Build());
                }

                if (processLiveRepresentation?.lastAppConfig != null)
                {
                    var publicWebHostUrls = configuration.GetSettingPublicWebHostUrls();

                    var webHost = buildWebHost(
                        processLiveRepresentation.lastAppConfig,
                        publicWebHostUrls: publicWebHostUrls);

                    webHost.StartAsync(appLifetime.ApplicationStopping).Wait();

                    logger.LogInformation("Started the public app at '" + string.Join(",", publicWebHostUrls) + "'.");

                    publicAppHost = new PublicHostConfiguration(
                        processLiveRepresentation: processLiveRepresentation,
                        webHost: webHost);
                }
            }
        }

        startPublicApp();

        app.Run(async(context) =>
        {
            var syncIOFeature = context.Features.Get <Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature>();
            if (syncIOFeature != null)
            {
                syncIOFeature.AllowSynchronousIO = true;
            }

            {
                context.Request.Headers.TryGetValue("Authorization", out var requestAuthorizationHeaderValue);

                context.Response.Headers.Add("X-Powered-By", "Elm Fullstack " + elm_fullstack.Program.AppVersionId);

                AuthenticationHeaderValue.TryParse(
                    requestAuthorizationHeaderValue.FirstOrDefault(), out var requestAuthorization);

                if (!(0 < adminPassword?.Length))
                {
                    context.Response.StatusCode = 403;
                    await context.Response.WriteAsync("The admin interface is not available because the admin password is not yet configured.");
                    return;
                }

                var buffer = new byte[400];

                var decodedRequestAuthorizationParameter =
                    Convert.TryFromBase64String(requestAuthorization?.Parameter ?? "", buffer, out var bytesWritten) ?
                    Encoding.UTF8.GetString(buffer, 0, bytesWritten) : null;

                var requestAuthorizationPassword =
                    decodedRequestAuthorizationParameter?.Split(':')?.ElementAtOrDefault(1);

                if (!(string.Equals(adminPassword, requestAuthorizationPassword) &&
                      string.Equals("basic", requestAuthorization?.Scheme, StringComparison.OrdinalIgnoreCase)))
                {
                    context.Response.StatusCode = 401;
                    context.Response.Headers.Add(
                        "WWW-Authenticate",
                        @"Basic realm=""" + context.Request.Host + @""", charset=""UTF-8""");
                    await context.Response.WriteAsync("Unauthorized");
                    return;
                }
            }

            async System.Threading.Tasks.Task deployElmApp(bool initElmAppState)
            {
                var memoryStream = new MemoryStream();
                context.Request.Body.CopyTo(memoryStream);

                var webAppConfigZipArchive = memoryStream.ToArray();

                {
                    try
                    {
                        var filesFromZipArchive = ZipArchive.EntriesFromZipArchive(webAppConfigZipArchive).ToImmutableList();

                        if (filesFromZipArchive.Count < 1)
                        {
                            throw new Exception("Contains no files.");
                        }
                    }
                    catch (Exception e)
                    {
                        context.Response.StatusCode = 400;
                        await context.Response.WriteAsync("Malformed web app config zip-archive:\n" + e);
                        return;
                    }
                }

                var appConfigTree =
                    Composition.SortedTreeFromSetOfBlobsWithCommonFilePath(
                        ZipArchive.EntriesFromZipArchive(webAppConfigZipArchive));

                var appConfigComponent = Composition.FromTreeWithStringPath(appConfigTree);

                var appConfigHashBase16 = CommonConversion.StringBase16FromByteArray(Composition.GetHash(appConfigComponent));

                logger.LogInformation("Got request to deploy app config " + appConfigHashBase16);

                processStoreWriter.StoreComponent(appConfigComponent);

                var appConfigValueInFile =
                    new ValueInFileStructure
                {
                    HashBase16 = appConfigHashBase16
                };

                var compositionLogEvent =
                    CompositionLogRecordInFile.CompositionEvent.EventForDeployAppConfig(
                        appConfigValueInFile: appConfigValueInFile,
                        initElmAppState: initElmAppState);

                await attemptContinueWithCompositionEventAndSendHttpResponse(compositionLogEvent);
            }

            var apiRoutes = new[]
            {
                new ApiRoute
                (
                    path: PathApiGetDeployedAppConfig,
                    methods: ImmutableDictionary <string, Func <HttpContext, PublicHostConfiguration?, System.Threading.Tasks.Task> > .Empty
                    .Add("get", async(context, publicAppHost) =>
                {
                    var appConfig = publicAppHost?.processLiveRepresentation?.lastAppConfig.appConfigComponent;

                    if (appConfig == null)
                    {
                        context.Response.StatusCode = 404;
                        await context.Response.WriteAsync("I did not find an app config in the history. Looks like no app was deployed so far.");
                        return;
                    }

                    var appConfigHashBase16 = CommonConversion.StringBase16FromByteArray(Composition.GetHash(appConfig));

                    var appConfigTree = Composition.ParseAsTreeWithStringPath(appConfig).Ok;

                    if (appConfigTree == null)
                    {
                        throw   new Exception("Failed to parse as tree with string path");
                    }

                    var appConfigZipArchive =
                        ZipArchive.ZipArchiveFromEntries(
                            Composition.TreeToFlatDictionaryWithPathComparer(appConfigTree));

                    context.Response.StatusCode            = 200;
                    context.Response.Headers.ContentLength = appConfigZipArchive.LongLength;
                    context.Response.Headers.Add("Content-Disposition", new ContentDispositionHeaderValue("attachment")
                    {
                        FileName = appConfigHashBase16 + ".zip"
                    }.ToString());
                    context.Response.Headers.Add("Content-Type", new MediaTypeHeaderValue("application/zip").ToString());

                    await context.Response.Body.WriteAsync(appConfigZipArchive);
                })
                ),
                new ApiRoute
                (
                    path: PathApiElmAppState,
                    methods: ImmutableDictionary <string, Func <HttpContext, PublicHostConfiguration?, System.Threading.Tasks.Task> > .Empty
                    .Add("get", async(context, publicAppHost) =>
                {
                    if (publicAppHost == null)
                    {
                        context.Response.StatusCode = 400;
                        await context.Response.WriteAsync("Not possible because there is no app (state).");
                        return;
                    }

                    var processLiveRepresentation = publicAppHost?.processLiveRepresentation;

                    var components = new List <Composition.Component>();

                    var storeWriter = new DelegatingProcessStoreWriter
                                      (
                        StoreComponentDelegate: components.Add,
                        StoreProvisionalReductionDelegate: _ => { },
                        AppendCompositionLogRecordDelegate: _ => throw new Exception("Unexpected use of interface.")
                                      );

                    var reductionRecord =
                        processLiveRepresentation?.StoreReductionRecordForCurrentState(storeWriter).reductionRecord;

                    if (reductionRecord == null)
                    {
                        context.Response.StatusCode = 500;
                        await context.Response.WriteAsync("Not possible because there is no Elm app deployed at the moment.");
                        return;
                    }

                    var elmAppStateReductionHashBase16 = reductionRecord.elmAppState?.HashBase16;

                    var elmAppStateReductionComponent =
                        components.First(c => CommonConversion.StringBase16FromByteArray(Composition.GetHash(c)) == elmAppStateReductionHashBase16);

                    if (elmAppStateReductionComponent.BlobContent == null)
                    {
                        throw   new Exception("elmAppStateReductionComponent is not a blob");
                    }

                    var elmAppStateReductionString =
                        Encoding.UTF8.GetString(elmAppStateReductionComponent.BlobContent);

                    context.Response.StatusCode  = 200;
                    context.Response.ContentType = "application/json";
                    await context.Response.WriteAsync(elmAppStateReductionString);
                })
                    .Add("post", async(context, publicAppHost) =>
                {
                    if (publicAppHost == null)
                    {
                        context.Response.StatusCode = 400;
                        await context.Response.WriteAsync("Not possible because there is no app (state).");
                        return;
                    }

                    var elmAppStateToSet = new StreamReader(context.Request.Body, Encoding.UTF8).ReadToEndAsync().Result;

                    var elmAppStateComponent = Composition.Component.Blob(Encoding.UTF8.GetBytes(elmAppStateToSet));

                    var appConfigValueInFile =
                        new ValueInFileStructure
                    {
                        HashBase16 = CommonConversion.StringBase16FromByteArray(Composition.GetHash(elmAppStateComponent))
                    };

                    processStoreWriter.StoreComponent(elmAppStateComponent);

                    await attemptContinueWithCompositionEventAndSendHttpResponse(
                        new CompositionLogRecordInFile.CompositionEvent
                    {
                        SetElmAppState = appConfigValueInFile
                    });
                })
                ),
                new ApiRoute
                (
                    path: PathApiDeployAndInitAppState,
                    methods: ImmutableDictionary <string, Func <HttpContext, PublicHostConfiguration?, System.Threading.Tasks.Task> > .Empty
                    .Add("post", async(context, publicAppHost) => await deployElmApp(initElmAppState: true))
                ),
                new ApiRoute
                (
                    path: PathApiDeployAndMigrateAppState,
                    methods: ImmutableDictionary <string, Func <HttpContext, PublicHostConfiguration?, System.Threading.Tasks.Task> > .Empty
                    .Add("post", async(context, publicAppHost) => await deployElmApp(initElmAppState: false))
                ),
                new ApiRoute
                (
                    path: PathApiReplaceProcessHistory,
                    methods: ImmutableDictionary <string, Func <HttpContext, PublicHostConfiguration?, System.Threading.Tasks.Task> > .Empty
                    .Add("post", async(context, publicAppHost) =>
                {
                    var memoryStream = new MemoryStream();
                    context.Request.Body.CopyTo(memoryStream);

                    var webAppConfigZipArchive = memoryStream.ToArray();

                    var replacementFiles =
                        ZipArchive.EntriesFromZipArchive(webAppConfigZipArchive)
                        .Select(filePathAndContent =>
                                (path: filePathAndContent.name.Split(new[] { '/', '\\' }).ToImmutableList()
                                 , filePathAndContent.content))
                        .ToImmutableList();

                    lock (avoidConcurrencyLock)
                    {
                        stopPublicApp();

                        foreach (var filePath in processStoreFileStore.ListFilesInDirectory(ImmutableList <string> .Empty).ToImmutableList())
                        {
                            processStoreFileStore.DeleteFile(filePath);
                        }

                        foreach (var replacementFile in replacementFiles)
                        {
                            processStoreFileStore.SetFileContent(replacementFile.path, replacementFile.content);
                        }

                        startPublicApp();
                    }

                    context.Response.StatusCode = 200;
                    await context.Response.WriteAsync("Successfully replaced the process history.");
                })
                ),
            };

            foreach (var apiRoute in apiRoutes)
            {
                if (!context.Request.Path.Equals(new PathString(apiRoute.path)))
                {
                    continue;
                }

                var matchingMethod =
                    apiRoute.methods
                    .FirstOrDefault(m => m.Key.ToUpperInvariant() == context.Request.Method.ToUpperInvariant());

                if (matchingMethod.Value == null)
                {
                    var supportedMethodsNames =
                        apiRoute.methods.Keys.Select(m => m.ToUpperInvariant()).ToList();

                    var guide =
                        HtmlFromLines(
                            "<h2>Method Not Allowed</h2>",
                            "",
                            context.Request.Path.ToString() +
                            " is a valid path, but the method " + context.Request.Method.ToUpperInvariant() +
                            " is not supported here.",
                            "Only following " +
                            (supportedMethodsNames.Count == 1 ? "method is" : "methods are") +
                            " supported here: " + string.Join(", ", supportedMethodsNames),
                            "", "",
                            ApiGuide);

                    context.Response.StatusCode = 405;
                    await context.Response.WriteAsync(HtmlDocument(guide));
                    return;
                }

                matchingMethod.Value?.Invoke(context, publicAppHost);
                return;
            }

            if (context.Request.Path.StartsWithSegments(new PathString(PathApiRevertProcessTo),
                                                        out var revertToRemainingPath))
            {
                if (!string.Equals(context.Request.Method, "post", StringComparison.InvariantCultureIgnoreCase))
                {
                    context.Response.StatusCode = 405;
                    await context.Response.WriteAsync("Method not supported.");
                    return;
                }

                var processVersionId = revertToRemainingPath.ToString().Trim('/');

                var processVersionCompositionRecord =
                    new ProcessStoreReaderInFileStore(processStoreFileStore)
                    .EnumerateSerializedCompositionLogRecordsReverse()
                    .FirstOrDefault(compositionEntry => CompositionLogRecordInFile.HashBase16FromCompositionRecord(compositionEntry) == processVersionId);

                if (processVersionCompositionRecord == null)
                {
                    context.Response.StatusCode = 404;
                    await context.Response.WriteAsync("Did not find process version '" + processVersionId + "'.");
                    return;
                }

                await attemptContinueWithCompositionEventAndSendHttpResponse(new CompositionLogRecordInFile.CompositionEvent
                {
                    RevertProcessTo = new ValueInFileStructure {
                        HashBase16 = processVersionId
                    },
                });
                return;
            }

            TruncateProcessHistoryReport truncateProcessHistory(TimeSpan productionBlockDurationLimit)
            {
                var beginTime = CommonConversion.TimeStringViewForReport(DateTimeOffset.UtcNow);

                var totalStopwatch = System.Diagnostics.Stopwatch.StartNew();

                var numbersOfThreadsToDeleteFiles = 4;

                var filePathsInProcessStorePartitions =
                    processStoreFileStore.ListFiles()
                    .Select((s, i) => (s, i))
                    .GroupBy(x => x.i % numbersOfThreadsToDeleteFiles)
                    .Select(g => g.Select(x => x.s).ToImmutableList())
                    .ToImmutableList();

                lock (avoidConcurrencyLock)
                {
                    var lockStopwatch = System.Diagnostics.Stopwatch.StartNew();

                    var storeReductionStopwatch = System.Diagnostics.Stopwatch.StartNew();

                    var storeReductionReport =
                        publicAppHost?.processLiveRepresentation?.StoreReductionRecordForCurrentState(processStoreWriter).report;

                    storeReductionStopwatch.Stop();

                    var getFilesForRestoreStopwatch = System.Diagnostics.Stopwatch.StartNew();

                    var filesForRestore =
                        PersistentProcess.PersistentProcessLiveRepresentation.GetFilesForRestoreProcess(
                            processStoreFileStore).files
                        .Select(filePathAndContent => filePathAndContent.Key)
                        .ToImmutableHashSet(EnumerableExtension.EqualityComparer <IImmutableList <string> >());

                    getFilesForRestoreStopwatch.Stop();

                    var deleteFilesStopwatch = System.Diagnostics.Stopwatch.StartNew();

                    var totalDeletedFilesCount =
                        filePathsInProcessStorePartitions
                        .AsParallel()
                        .WithDegreeOfParallelism(numbersOfThreadsToDeleteFiles)
                        .Select(partitionFilePaths =>
                    {
                        int partitionDeletedFilesCount = 0;

                        foreach (var filePath in partitionFilePaths)
                        {
                            if (filesForRestore.Contains(filePath))
                            {
                                continue;
                            }

                            if (productionBlockDurationLimit < lockStopwatch.Elapsed)
                            {
                                break;
                            }

                            processStoreFileStore.DeleteFile(filePath);
                            ++partitionDeletedFilesCount;
                        }

                        return(partitionDeletedFilesCount);
                    })
                        .Sum();

                    deleteFilesStopwatch.Stop();

                    return(new TruncateProcessHistoryReport
                           (
                               beginTime: beginTime,
                               filesForRestoreCount: filesForRestore.Count,
                               discoveredFilesCount: filePathsInProcessStorePartitions.Sum(partition => partition.Count),
                               deletedFilesCount: totalDeletedFilesCount,
                               storeReductionTimeSpentMilli: (int)storeReductionStopwatch.ElapsedMilliseconds,
                               storeReductionReport: storeReductionReport,
                               getFilesForRestoreTimeSpentMilli: (int)getFilesForRestoreStopwatch.ElapsedMilliseconds,
                               deleteFilesTimeSpentMilli: (int)deleteFilesStopwatch.ElapsedMilliseconds,
                               lockedTimeSpentMilli: (int)lockStopwatch.ElapsedMilliseconds,
                               totalTimeSpentMilli: (int)totalStopwatch.ElapsedMilliseconds
                           ));
                }
            }

            if (context.Request.Path.Equals(new PathString(PathApiTruncateProcessHistory)))
            {
                var truncateResult = truncateProcessHistory(productionBlockDurationLimit: TimeSpan.FromMinutes(1));

                context.Response.StatusCode  = 200;
                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(truncateResult));
                return;
            }

            {
                if (context.Request.Path.StartsWithSegments(
                        new PathString(PathApiProcessHistoryFileStoreGetFileContent), out var remainingPathString))
                {
                    if (!string.Equals(context.Request.Method, "get", StringComparison.InvariantCultureIgnoreCase))
                    {
                        context.Response.StatusCode = 405;
                        await context.Response.WriteAsync("Method not supported.");
                        return;
                    }

                    var filePathInStore =
                        remainingPathString.ToString().Trim('/').Split('/').ToImmutableList();

                    var fileContent = processStoreFileStore.GetFileContent(filePathInStore);

                    if (fileContent == null)
                    {
                        context.Response.StatusCode = 404;
                        await context.Response.WriteAsync("No file at '" + string.Join("/", filePathInStore) + "'.");
                        return;
                    }

                    context.Response.StatusCode  = 200;
                    context.Response.ContentType = "application/octet-stream";
                    await context.Response.Body.WriteAsync(fileContent as byte[] ?? fileContent.ToArray());
                    return;
                }
            }

            {
                if (context.Request.Path.StartsWithSegments(
                        new PathString(PathApiProcessHistoryFileStoreListFilesInDirectory), out var remainingPathString))
                {
                    if (!string.Equals(context.Request.Method, "get", StringComparison.InvariantCultureIgnoreCase))
                    {
                        context.Response.StatusCode = 405;
                        await context.Response.WriteAsync("Method not supported.");
                        return;
                    }

                    var filePathInStore =
                        remainingPathString.ToString().Trim('/').Split('/').ToImmutableList();

                    var filesPaths = processStoreFileStore.ListFilesInDirectory(filePathInStore);

                    var filesPathsList =
                        string.Join('\n', filesPaths.Select(path => string.Join('/', path)));

                    context.Response.StatusCode  = 200;
                    context.Response.ContentType = "application/octet-stream";
                    await context.Response.Body.WriteAsync(Encoding.UTF8.GetBytes(filesPathsList));
                    return;
                }
            }

            (int statusCode, AttemptContinueWithCompositionEventReport responseReport)attemptContinueWithCompositionEvent(
                CompositionLogRecordInFile.CompositionEvent compositionLogEvent)
            {
                lock (avoidConcurrencyLock)
                {
                    var storeReductionStopwatch = System.Diagnostics.Stopwatch.StartNew();

                    var storeReductionReport =
                        publicAppHost?.processLiveRepresentation?.StoreReductionRecordForCurrentState(processStoreWriter).report;

                    storeReductionStopwatch.Stop();

                    var(statusCode, report) =
                        AttemptContinueWithCompositionEventAndCommit(
                            compositionLogEvent,
                            processStoreFileStore,
                            testContinueLogger: logEntry => logger.LogInformation(logEntry));

                    report = report with
                    {
                        storeReductionTimeSpentMilli = (int)storeReductionStopwatch.ElapsedMilliseconds,
                        storeReductionReport         = storeReductionReport
                    };

                    startPublicApp();

                    return(statusCode, report);
                }
            }

            async System.Threading.Tasks.Task attemptContinueWithCompositionEventAndSendHttpResponse(
                CompositionLogRecordInFile.CompositionEvent compositionLogEvent,
                ILogger? logger = null)
            {
                logger?.LogInformation(
                    "Begin attempt to continue with composition event: " +
                    System.Text.Json.JsonSerializer.Serialize(compositionLogEvent));

                var(statusCode, attemptReport) = attemptContinueWithCompositionEvent(compositionLogEvent);

                var responseBodyString = System.Text.Json.JsonSerializer.Serialize(attemptReport);

                context.Response.StatusCode = statusCode;
                await context.Response.WriteAsync(responseBodyString);
            }

            if (context.Request.Path.Equals(PathString.Empty) || context.Request.Path.Equals(new PathString("/")))
            {
                var httpApiGuide =
                    HtmlFromLines(
                        "<h3>HTTP APIs</h3>\n" +
                        HtmlFromLines(apiRoutes.Select(HtmlToDescribeApiRoute).ToArray())
                        );

                context.Response.StatusCode = 200;
                await context.Response.WriteAsync(
                    HtmlDocument(
                        HtmlFromLines(
                            "Welcome to the Elm Fullstack admin interface version " + elm_fullstack.Program.AppVersionId + ".",
                            httpApiGuide,
                            "",
                            ApiGuide)));
                return;
            }

            context.Response.StatusCode = 404;
            await context.Response.WriteAsync("Not Found");
            return;
        });
    }
        protected override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            //We are expecting a header such as Authorization: <Schema> <key>
            //If this is not present, we will return NoResult and move on to the next authentication handler.
            if (!Request.Headers.TryGetValue(HeaderNames.Authorization, out StringValues values) ||
                !values.Any())
            {
                return(Task.FromResult(AuthenticateResult.NoResult()));
            }

            if (!AuthenticationHeaderValue.TryParse(values.First(), out AuthenticationHeaderValue authHeader))
            {
                return(Task.FromResult(AuthenticateResult.Fail("Invalid authentication header")));
            }

            if (!string.Equals(authHeader.Scheme, Scheme.Name, StringComparison.OrdinalIgnoreCase))
            {
                return(Task.FromResult(AuthenticateResult.NoResult()));
            }

            //The user is passing a base 64-encoded version of the secret
            //We will be hash this and compare it to the secret in our configuration.
            byte[]      secret = new byte[32];
            Span <byte> span   = new Span <byte>(secret);

            if (!Convert.TryFromBase64String(authHeader.Parameter, span, out int bytesWritten) || bytesWritten < 32)
            {
                return(Task.FromResult(AuthenticateResult.Fail("Invalid Api Key format")));
            }

            //HACK IOptionsMonitor and similiar do not properly update here even though the underlying
            //configuration is updated. We get the value directly from IConfiguration.

            var            authenticationOptions = new ApiAuthenticationOptions();
            IConfiguration configService         = Context.RequestServices.GetRequiredService <IConfiguration>();

            configService.Bind(ApiAuthenticationOptions.ConfigurationKey, authenticationOptions);
            string apiKeyHash = authenticationOptions.ApiKeyHash;

            if (apiKeyHash == null)
            {
                return(Task.FromResult(AuthenticateResult.Fail("Server does not contain Api Key")));
            }
            if (string.IsNullOrEmpty(authenticationOptions.ApiKeyHashType))
            {
                return(Task.FromResult(AuthenticateResult.Fail("Missing hash algorithm")));
            }
            if (DisallowedHashAlgorithms.Contains(authenticationOptions.ApiKeyHashType, StringComparer.OrdinalIgnoreCase))
            {
                return(Task.FromResult(AuthenticateResult.Fail($"Disallowed hash algorithm {authenticationOptions.ApiKeyHashType}")));
            }

            using HashAlgorithm algorithm = HashAlgorithm.Create(authenticationOptions.ApiKeyHashType);
            if (algorithm == null)
            {
                return(Task.FromResult(AuthenticateResult.Fail($"Invalid hash algorithm {authenticationOptions.ApiKeyHashType}")));
            }

            byte[] hashedSecret = algorithm.ComputeHash(secret);

            //ApiKeyHash is represented as a hex string. e.g. AABBCCDDEEFF
            byte[] apiKeyHashBytes = new byte[apiKeyHash.Length / 2];
            for (int i = 0; i < apiKeyHash.Length; i += 2)
            {
                if (!byte.TryParse(apiKeyHash.AsSpan(i, 2), NumberStyles.HexNumber, provider: NumberFormatInfo.InvariantInfo, result: out byte resultByte))
                {
                    return(Task.FromResult(AuthenticateResult.Fail("Invalid Api Key hash")));
                }
                apiKeyHashBytes[i / 2] = resultByte;
            }

            if (hashedSecret.SequenceEqual(apiKeyHashBytes))
            {
                return(Task.FromResult(AuthenticateResult.Success(
                                           new AuthenticationTicket(
                                               new ClaimsPrincipal(new[] { new ClaimsIdentity(AuthConstants.ApiKeySchema) }),
                                               AuthConstants.ApiKeySchema))));
            }
            else
            {
                return(Task.FromResult(AuthenticateResult.Fail("Invalid Api Key")));
            }
        }
Esempio n. 23
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            try
            {
                this.Logger.LogInformation("{LogKey:l} apikey handle", LogKeys.Authentication);

                if (this.Request.Host.Host.SafeEquals("localhost") && this.Options.IgnoreLocal)
                {
                    // ignore for localhost
                    var identity = new ClaimsIdentity(
                        this.Options.Claims.Safe().Select(c => new Claim(c.Key, c.Value))
                        .Insert(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationKeys.ApiKeyScheme))
                        .Insert(new Claim(ClaimTypes.Name, ClaimsIdentity.DefaultIssuer))
                        .DistinctBy(c => c.Type),
                        this.Scheme.Name);
                    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
                    this.Logger.LogInformation($"{{LogKey:l}} apikey authenticated (name={identity.Name})", LogKeys.Authentication);

                    return(AuthenticateResult.Success(ticket));
                }

                string value;
                if (this.Request.Query.TryGetValue("apikey", out var queryValue))
                {
                    // also allow the auth header to be sent in the querystring (for easy dashboard usage)
                    value = queryValue.ToString();
                }
                else
                {
                    if (!this.Request.Headers.ContainsKey(AuthenticationKeys.AuthorizationHeaderName))
                    {
                        return(AuthenticateResult.NoResult()); //Authorization header not in request
                    }

                    if (!AuthenticationHeaderValue.TryParse(this.Request.Headers[AuthenticationKeys.AuthorizationHeaderName], out var headerValue))
                    {
                        return(AuthenticateResult.NoResult()); //Invalid Authorization header
                    }
                    else
                    {
                        value = headerValue.Parameter;
                    }

                    if (!AuthenticationKeys.ApiKeyScheme.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
                    {
                        return(AuthenticateResult.NoResult()); //Not a apikey authentication header
                    }
                }

                if (value.IsNullOrEmpty())
                {
                    return(AuthenticateResult.NoResult()); //No apikey authentication value in header or query
                }

                //var context = new ApiKeyValidationContext(this.Context, this.Scheme, this.Options) { ApiKey = headerValue.Parameter };
                //await this.Events.OnValidation(context);
                //if (context.Result != null)
                //{
                //    return context.Result;
                //}

#pragma warning disable SA1008 // Opening parenthesis must be spaced correctly
                var(authenticated, claims) = this.service.Validate(value);
#pragma warning restore SA1008 // Opening parenthesis must be spaced correctly
                if (authenticated)
                {
                    var identity = new ClaimsIdentity(
                        this.Options.Claims.Safe().Select(c => new Claim(c.Key, c.Value)).Concat(claims.Safe())
                        .Insert(new Claim(ClaimTypes.AuthenticationMethod, AuthenticationKeys.ApiKeyScheme)).DistinctBy(c => c.Type),
                        this.Scheme.Name);
                    var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), this.Scheme.Name);
                    this.Logger.LogInformation($"{{LogKey:l}} apikey authenticated (name={identity.Name})", LogKeys.Authentication);

                    return(AuthenticateResult.Success(ticket));
                }

                this.Logger.LogWarning("{LogKey:l} apikey not authenticated", LogKeys.Authentication);
                return(AuthenticateResult.Fail("not authenticated"));
            }
            catch (Exception ex)
            {
                this.Logger.LogError(ex, $"{{LogKey:l}} {ex.Message}", LogKeys.Authentication);
                var context = new ErrorContext(this.Context, this.Scheme, this.Options)
                {
                    Exception = ex
                };
                if (this.Events != null)
                {
                    await this.Events.Error(context);

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

                throw;
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var now = _systemClock.UtcNow.UtcDateTime;

            if (!Request.Headers.ContainsKey("Authorization"))
            {
                Logger.LogError("Missing Authorization Header");
                return(AuthenticateResult.Fail("Missing Authorization Header"));
            }

            ClaimsPrincipal principal = null;

            try
            {
                AuthenticationHeaderValue authenticationHeader;

                if (AuthenticationHeaderValue.TryParse(Request.Headers["Authorization"], out authenticationHeader))
                {
                    if (authenticationHeader.Scheme == "Basic")
                    {
                        var credentialBytes  = Convert.FromBase64String(authenticationHeader.Parameter);
                        var credentialString = Encoding.UTF8.GetString(credentialBytes);

                        if (credentialString.Contains(":"))
                        {
                            var credentials = credentialString.Split(new[] { ':' }, 2);
                            var email       = credentials[0];
                            var password    = credentials[1];
                            var user        = await _authenticationService.AuthenticateUserWithPassword(email, password);

                            if (user == null)
                            {
                                //bad password
                                Logger.LogError("Invalid Username or password");
                                return(AuthenticateResult.Fail("Invalid Username or Password"));
                            }
                            else
                            {
                                //make a token and put it in the response header?

                                Logger.LogInformation("Authenticated User {@email} via email/password", user.Email);

                                var jwt = await _authenticationService.IssueJwtToUser(user.Id);

                                principal = _authenticationService.ValidateSignedJwtToken(jwt);

                                Response.Headers.Add("Authorization", "Token " + jwt);
                            }
                        }
                    }
                    else if (authenticationHeader.Scheme == "Token" || authenticationHeader.Scheme == "Bearer") //TODO: remove "Token"
                    {
                        if ((new JwtSecurityTokenHandler()).CanReadToken(authenticationHeader.Parameter))
                        {
                            var jwtPrincipal = _authenticationService.ValidateSignedJwtToken(authenticationHeader.Parameter);
                            var parsed       = jwtPrincipal.ParseAllClaims();

                            //TODO: update this so that only superseded/expired token are in the db, "good" tokens will not be
                            var token = await _tokenRepository.GetToken(parsed.Token.TokenGuid);

                            if (token == null || (token.ExpiredAt.HasValue && token.ExpiredAt < now))
                            {
                                //note we do NOT set the principle, it's expired so we let it fail as invalid
                            }
                            else if ((parsed.Minimal.HasValue && parsed.Minimal.Value) || (token.SupersededAt.HasValue && token.SupersededAt < now))
                            {
                                //token is valid, but needs to be updated due to some change that was made to data contained therein
                                //OR the token is a minimal one which needs to be repalced with a "full" token
                                var refreshedJwt = await _authenticationService.IssueJwtToUser(parsed.User.Id, token.TokenGuid);

                                //send the updated token back to client
                                Response.Headers.Add("Authorization", "Token " + refreshedJwt);

                                principal = _authenticationService.ValidateSignedJwtToken(refreshedJwt);
                            }
                            else
                            {
                                principal = jwtPrincipal;
                            }

                            Logger.LogInformation("Authenticated User {@id} via bearer token {@tokenGuid}", parsed.User.Id, parsed.Token.TokenGuid);
                        }
                    }
                    else
                    {
                        Logger.LogError("Invalid Authorization Header");
                        //it's not a token and it's not a basic, what is it?
                        return(AuthenticateResult.Fail("Invalid Authorization Header"));
                    }
                }
                else
                {
                    Logger.LogError("Invalid Authorization Header");
                    //we can't understand the auth header
                    return(AuthenticateResult.Fail("Invalid Authorization Header"));
                }
            }
            catch (Exception ex)
            {
                Logger.LogError("Exception in Authorization {@ex}", ex);
                //some exception we weren't ready for, likely a malformed header
                return(AuthenticateResult.Fail("Invalid Authorization Header"));
            }

            if (principal == null)
            {
                //this shouldn't actually happen, but just in case
                Logger.LogError("Invalid Username or Password");
                return(AuthenticateResult.Fail("Invalid Username or Password"));
            }

            var ticket = new AuthenticationTicket(principal, Scheme.Name);

            return(AuthenticateResult.Success(ticket));
        }
Esempio n. 25
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey(AuthorizationHeaderName))
            {
                //Authorization header not in request
                return(AuthenticateResult.NoResult());
            }

            if (!AuthenticationHeaderValue.TryParse(Request.Headers[AuthorizationHeaderName], out AuthenticationHeaderValue headerValue))
            {
                //Invalid Authorization header
                return(AuthenticateResult.NoResult());
            }

            if (!BasicSchemeName.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                //Not Basic authentication header
                return(AuthenticateResult.NoResult());
            }

            try
            {
                if (string.IsNullOrEmpty(headerValue.Parameter))
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidToken, "Invalid token")));
                }
                byte[]   headerValueBytes = Convert.FromBase64String(headerValue.Parameter);
                string   userAndPassword  = Encoding.UTF8.GetString(headerValueBytes);
                string[] parts            = userAndPassword.Split(':');
                if (parts.Length != 2)
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidAutheHeader, "Invalid Basic authentication header")));
                }
                string tenancyName = parts[0];
                string apiKey      = parts[1];

                string userId   = "";
                string tenantId = "";
                if (!string.IsNullOrEmpty(tenancyName))
                {
                    var tenants = await _tenantRepository.GetAll().IgnoreQueryFilters()
                                  .Where(o => o.ApiKey == apiKey && o.TenancyName == tenancyName && !o.IsDeleted && o.IsActive).ToListAsync();

                    if (tenants.Count == 0)
                    {
                        return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidInput, "Invalid tenancyname or apikey")));
                    }
                    if (!tenants[0].IsActive)
                    {
                        return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_RefuseAuthorization, "tenant is banish")));
                    }
                    var user = await this._userRepository.GetAll().IgnoreQueryFilters().SingleAsync(o => o.UserName == "admin" && o.TenantId == tenants[0].Id);

                    tenantId = tenants[0].Id.ToString();
                    userId   = user.Id.ToString();
                }
                else if (apiKey.Equals(Options.SystemApiKey))
                {
                    var user = await this._userRepository.GetAll().IgnoreQueryFilters().SingleAsync(o => o.UserName == "admin" && o.TenantId == null);

                    userId = user.Id.ToString();
                }
                else
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidInput, "Invalid tenancyname or apikey")));
                }
                var claims = new[] {
                    new Claim(ClaimTypes.NameIdentifier, userId),
                    new Claim(AbpClaimTypes.TenantId, tenantId),
                    new Claim(AbpClaimTypes.UserName, StaticRoleNames.Host.Admin)
                };
                var identity  = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);
                return(AuthenticateResult.Success(ticket));
            }
            catch (Exception ex) when(ex is FormatException || ex is DecoderFallbackException)
            {
                return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidToken, "Invalid token")));
            }
            catch (Exception ex)
            {
                LogHelper.Logger.Error("basic auth", ex);
                return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.SytemError, "Invalid auth request")));
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Cookies.ContainsKey(AccessToken) || !Request.Cookies.ContainsKey(User_Id))
            {
                Log.Error("No Access Token or User Id found.");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            if (!AuthenticationHeaderValue.TryParse($"{"Bearer " + Request.Cookies[AccessToken]}",
                                                    out AuthenticationHeaderValue headerValue))
            {
                Log.Error("Could not Parse Token from Authentication Header.");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            if (!AuthenticationHeaderValue.TryParse($"{"Bearer " + Request.Cookies[User_Id]}",
                                                    out AuthenticationHeaderValue headerValueUid))
            {
                Log.Error("Could not Parse User Id from Authentication Header.");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            try
            {
                /* STEP 1. Get the Validation Parameters for our applications JWT Token */
                var key = Encoding.ASCII.GetBytes(_appSettings.Secret);

                /* STEP 2. Create an instance of Jwt token handler */
                var handler = new JwtSecurityTokenHandler();

                /* STEP 3. Create an instance of Jwt token  validation parameters */
                TokenValidationParameters validationParameters =
                    new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer           = true,
                    ValidateAudience         = true,
                    ValidIssuer      = _appSettings.Site,
                    ValidAudience    = _appSettings.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateLifetime = true,
                    ClockSkew        = TimeSpan.Zero
                };

                /* STEP 4. Get the Data protection service instance */
                var protectorProvider = _provider.GetService <IDataProtectionProvider>();

                /* STEP 5. create a protector instance */
                var protector = protectorProvider.CreateProtector(_dataProtectionKeys.ApplicationUserKey);

                /* STEP 6. Layer One Unprotect the user id */
                var decryptedUid = protector.Unprotect(headerValueUid.Parameter);

                /* STEP 7. Layer One Unprotect the user token */
                var decryptedToken = protector.Unprotect(headerValue.Parameter);

                /* STEP 8. Create an instance of the user tokenModel */
                TokenEntities tokenModel = new TokenEntities();

                /* STEP 9 Get the existing token for the user from Database using a scoped request */

                using (var scope = _provider.CreateScope())
                {
                    var dbContextService = scope.ServiceProvider.GetService <ApplicationDbContext>();
                    var userToken        = dbContextService.Tokens.Include(x => x.User)
                                           .FirstOrDefault(ut => ut.UserId == decryptedUid &&
                                                           ut.User.UserName == Request.Cookies[Username] &&
                                                           ut.User.Id == decryptedUid &&
                                                           ut.User.UserRole == "Administrator");
                    tokenModel = userToken;
                }

                /* Step 11. Check if tokenmodel is null */
                if (tokenModel == null)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("You are not authorized to View this Page")));
                }

                /* STEP 12. Apply second layer of decryption using the key store in the token model */
                /* STEP 12.1 Create Protector instance for layer two using token model key */
                /* IMPORTANT - If no key exists or key is invalid - exception will be thrown */
                IDataProtector layerTwoProtector      = protectorProvider.CreateProtector(tokenModel?.EncryptionKeyJwt);
                string         decryptedTokenLayerTwo = layerTwoProtector.Unprotect(decryptedToken);


                /* STEP 13. Validate the token we received - using validation parameters set in step 3 */
                /* IMPORTANT - If the validation fails - the method ValidateToken will throw exception */
                var validateToken = handler.ValidateToken(decryptedTokenLayerTwo, validationParameters, out var securityToken);

                /* STEP 14. Checking Token Signature */
                if (!(securityToken is JwtSecurityToken jwtSecurityToken) ||
                    !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256,
                                                        StringComparison.InvariantCultureIgnoreCase))
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized")));
                }

                /* STEP 15. Extract the username from the validated token */
                var username = validateToken.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;

                if (Request.Cookies[Username] != username)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("You are not authorized to View this Page")));
                }


                /* STEP 16. Get User by their email */
                var user = await _userManager.FindByNameAsync(username);

                /* STEP 17. If user does not exist return authentication failed result */
                if (user == null)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("You are not authorized to View this Page")));
                }

                /* STEP 18. We need to check if the user belongs to the group of user-roles */

                if (!UserRoles.Contains(user.UserRole))
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("You are not authorized to View this Page")));
                }

                /* STEP 19. Now we will create an authentication ticket, as the token is valid */
                var identity  = new ClaimsIdentity(validateToken.Claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);
                return(await Task.FromResult(AuthenticateResult.Success(ticket)));
            }
            catch (Exception ex)
            {
                Log.Error("An error occurred while seeding the database  {Error} {StackTrace} {InnerException} {Source}",
                          ex.Message, ex.StackTrace, ex.InnerException, ex.Source);
                return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized")));
            }
        }
Esempio n. 27
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey(AuthorizationHeaderName))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!AuthenticationHeaderValue.TryParse(Request.Headers[AuthorizationHeaderName], out AuthenticationHeaderValue headerValue))
            {
                //Invalid Authorization header
                return(AuthenticateResult.NoResult());
            }

            if (!BasicSchemeName.Equals(headerValue.Scheme, StringComparison.OrdinalIgnoreCase))
            {
                //Not Basic authentication header
                return(AuthenticateResult.NoResult());
            }

            try
            {
                if (string.IsNullOrEmpty(headerValue.Parameter))
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidToken, "Invalid token")));
                }
                byte[]   headerValueBytes = Convert.FromBase64String(headerValue.Parameter);
                string   userAndPassword  = Encoding.UTF8.GetString(headerValueBytes);
                string[] parts            = userAndPassword.Split(':');
                if (parts.Length != 2)
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidAutheHeader, "Invalid Basic authentication header")));
                }
                string otherSystemName = parts[0];
                string certificate     = parts[1];

                var os = await this._osRepository.FirstOrDefaultAsync(o => o.SystemName == otherSystemName && o.Certificate == certificate);

                if (os == null)
                {
                    return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_RefuseAuthorization, "os is banish")));
                }
                var user = await this._userRepository.SingleAsync(o => o.UserName == StaticRoleNames.Host.Admin && o.TenantId == null);

                var claims = new[] {
                    new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                    new Claim(AbpClaimTypes.UserName, StaticRoleNames.Host.Admin),
                    new Claim("SplitPackageOtherSystemId", os.Id.ToString())
                };
                var identity  = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);
                return(AuthenticateResult.Success(ticket));
            }
            catch (Exception ex) when(ex is FormatException || ex is DecoderFallbackException)
            {
                return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.Auth_InvalidToken, "Invalid token")));
            }
            catch (Exception ex)
            {
                LogHelper.Logger.Error("application auth", ex);
                return(AuthenticateResult.Fail(new Abp.UI.UserFriendlyException((int)Split.Dto.ResultCode.SytemError, "Invalid auth request")));
            }
        }
        protected override async Task <AuthenticationTicket> AuthenticateCoreAsync()
        {
            if (Request.Method.Equals("get", StringComparison.InvariantCultureIgnoreCase) &&
                !string.IsNullOrEmpty(Request.Uri.Query))
            {
                var query = HttpUtility.ParseQueryString(Request.Uri.Query);
                if (query["bewit"] != null)
                {
                    this.logger.WriteInformation(string.Format("Bewit found {0}",
                                                               query["bewit"]));
                    try
                    {
                        var principal = await Hawk.AuthenticateBewitAsync(query["bewit"],
                                                                          Request.Host.Value,
                                                                          Request.Uri,
                                                                          this.Options.Credentials);

                        var identity = (ClaimsIdentity)((ClaimsPrincipal)principal).Identity;
                        var ticket   = new AuthenticationTicket(identity, null);

                        return(ticket);
                    }
                    catch (SecurityException ex)
                    {
                        this.logger.WriteWarning("Unauthorized call. " + ex.Message);

                        return(EmptyTicket());
                    }
                }
            }

            AuthenticationHeaderValue authorization = null;

            if (Request.Headers.ContainsKey("authorization"))
            {
                AuthenticationHeaderValue.TryParse(Request.Headers["authorization"], out authorization);
            }

            if (authorization != null &&
                !string.Equals(authorization.Scheme, HawkAuthenticationOptions.Scheme))
            {
                this.logger.WriteInformation(string.Format("Authorization skipped. Schema found {0}",
                                                           authorization.Scheme));

                return(EmptyTicket());
            }

            if (authorization == null ||
                string.IsNullOrWhiteSpace(authorization.Scheme))
            {
                this.logger.WriteWarning("Authorization header not found");

                return(EmptyTicket());
            }
            else
            {
                if (string.IsNullOrWhiteSpace(authorization.Parameter))
                {
                    this.logger.WriteWarning("Invalid header format");

                    return(EmptyTicket());
                }

                if (string.IsNullOrWhiteSpace(Request.Host.Value))
                {
                    this.logger.WriteWarning("Missing Host header");

                    return(EmptyTicket());
                }

                Func <Task <string> > requestPayload = (async() =>
                {
                    var requestBuffer = new MemoryStream();
                    await Request.Body.CopyToAsync(requestBuffer).ConfigureAwait(false);
                    requestBuffer.Flush();

                    Request.Body = requestBuffer;

                    var payload = Encoding.UTF8.GetString(requestBuffer.ToArray());

                    return(payload);
                });

                try
                {
                    var principal = await Hawk.AuthenticateAsync(authorization.Parameter,
                                                                 Request.Host.Value,
                                                                 Request.Method,
                                                                 Request.Uri,
                                                                 this.Options.Credentials,
                                                                 this.Options.TimeskewInSeconds,
                                                                 requestPayload,
                                                                 Request.ContentType);

                    var identity = (ClaimsIdentity)((ClaimsPrincipal)principal).Identity;
                    var ticket   = new AuthenticationTicket(identity, null);

                    return(ticket);
                }
                catch (SecurityException ex)
                {
                    this.logger.WriteWarning(ex.Message);

                    return(EmptyTicket());
                }
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Cookies.ContainsKey(AccessToken) || !Request.Cookies.ContainsKey(User_Id))
            {
                Log.Error("No Access Token or User Id found");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            if (!AuthenticationHeaderValue.TryParse($"{"Bearer " + Request.Cookies[AccessToken]}",
                                                    out AuthenticationHeaderValue headerValue))
            {
                Log.Error("Could not parse Token from Authentication Header");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            if (!AuthenticationHeaderValue.TryParse($"{"Bearer " + Request.Cookies[User_Id]}",
                                                    out AuthenticationHeaderValue headerValueUid))
            {
                Log.Error("Could not parse User Id from Authentication Header");
                return(await Task.FromResult(AuthenticateResult.NoResult()));
            }

            try
            {
                var key     = Encoding.ASCII.GetBytes(_appSettings.Secret);
                var handler = new JwtSecurityTokenHandler();
                TokenValidationParameters validationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    ValidateIssuer           = true,
                    ValidateAudience         = true,
                    ValidIssuer      = _appSettings.Site,
                    ValidAudience    = _appSettings.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateLifetime = true,
                    ClockSkew        = TimeSpan.Zero
                };
                var        protectorProvider = _provider.GetService <IDataProtectionProvider>();
                var        protector         = protectorProvider.CreateProtector(_dataProtectionKeys.ApplicationUserKey);
                var        decryptedUid      = protector.Unprotect(headerValueUid.Parameter);
                var        decryptedToken    = protector.Unprotect(headerValue.Parameter);
                TokenModel tokenModel        = new TokenModel();

                using (var scope = _provider.CreateScope())
                {
                    var dbContextService = scope.ServiceProvider.GetService <ApplicationDbContext>();
                    var userToken        = dbContextService.Tokens.Include(x => x.User)
                                           .FirstOrDefault(UTF32Encoding => UTF32Encoding.UserId == decryptedUid &&
                                                           UTF32Encoding.User.UserName == Request.Cookies[Username] &&
                                                           UTF32Encoding.User.Id == decryptedUid &&
                                                           UTF32Encoding.User.UserRole == "Administrator");
                    tokenModel = userToken;
                }

                if (tokenModel == null)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized to view this page")));
                }

                IDataProtector layerTwoProtector      = protectorProvider.CreateProtector(tokenModel?.EncryptionKeyJwt);
                string         decryptedTokenLayerTwo = layerTwoProtector.Unprotect(decryptedToken);

                var validateToken = handler.ValidateToken(decryptedTokenLayerTwo, validationParameters, out var securityToken);

                /* Checking Token Signature */
                if (!(securityToken is JwtSecurityToken jwtSecurityToken) ||
                    !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized")));
                }

                var username = validateToken.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;

                if (Request.Cookies[Username] != username)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized to view this page")));
                }

                var user = await _userManager.FindByNameAsync(username);

                if (user == null)
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized to view this page")));
                }

                if (!UserRoles.Contains(user.UserRole))
                {
                    return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized to view this page")));
                }

                var identity  = new ClaimsIdentity(validateToken.Claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);
                return(await Task.FromResult(AuthenticateResult.Success(ticket)));
            }
            catch (Exception ex)
            {
                Log.Error("An error occured while authenticating {Error} {StackTrace} {InnerException} {Source}",
                          ex.Message, ex.StackTrace, ex.InnerException, ex.Source);
                return(await Task.FromResult(AuthenticateResult.Fail("Your are not authorized")));
            }
        }
Esempio n. 30
0
        public bool Authenticate(HttpContext context, out HttpAuthenticationRequest request)
        {
            if (context.Request.Headers.TryGetValue("authorization", out var values) && values.Count == 1 && AuthenticationHeaderValue.TryParse(
                    values[0], out var authenticationHeader) &&
                authenticationHeader.Scheme == "Basic" &&
                TryDecodeCredential(authenticationHeader.Parameter, out var username, out var password))
            {
                request = new HttpAuthenticationRequest(context, username, password);
                _internalAuthenticationProvider.Authenticate(request);
                return(true);
            }

            request = null;
            return(false);
        }