Exemple #1
0
        public async Task VerifyAccountControllerExternalLoginWithTokensFlow()
        {
            // Setup the external cookie like it would look from a real OAuth2
            var externalId       = "<externalId>";
            var authScheme       = "<authScheme>";
            var externalIdentity = new ClaimsIdentity();

            externalIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, externalId));
            var externalPrincipal = new ClaimsPrincipal(externalIdentity);
            var externalLogin     = new ExternalLoginInfo(externalPrincipal, authScheme, externalId, "displayname")
            {
                AuthenticationTokens = new[] {
                    new AuthenticationToken {
                        Name = "refresh_token", Value = "refresh"
                    },
                    new AuthenticationToken {
                        Name = "access_token", Value = "access"
                    }
                }
            };

            var context = new DefaultHttpContext();
            var auth    = MockAuth(context);

            auth.Setup(a => a.AuthenticateAsync(context, It.IsAny <string>())).Returns(Task.FromResult(AuthenticateResult.NoResult()));
            var contextAccessor = new Mock <IHttpContextAccessor>();

            contextAccessor.Setup(a => a.HttpContext).Returns(context);
            var services = new ServiceCollection()
                           .AddSingleton <IConfiguration>(new ConfigurationBuilder().Build())
                           .AddLogging()
                           .AddSingleton(contextAccessor.Object);

            services.AddIdentity <TestUser, TestRole>();
            services.AddSingleton <IUserStore <TestUser>, InMemoryStore <TestUser, TestRole> >();
            services.AddSingleton <IRoleStore <TestRole>, InMemoryStore <TestUser, TestRole> >();

            var app = new ApplicationBuilder(services.BuildServiceProvider());

            // Act
            var user = new TestUser
            {
                UserName = "******"
            };
            var userManager   = app.ApplicationServices.GetRequiredService <IUserManager <TestUser> >();
            var signInManager = app.ApplicationServices.GetRequiredService <SignInManager <TestUser> >();

            IdentityResultAssert.IsSuccess(await userManager.CreateAsync(user));
            IdentityResultAssert.IsSuccess(await userManager.AddLoginAsync(user, new UserLoginInfo(authScheme, externalId, "whatever")));
            IdentityResultAssert.IsSuccess(await signInManager.UpdateExternalAuthenticationTokensAsync(externalLogin));
            Assert.Equal("refresh", await userManager.GetAuthenticationTokenAsync(user, authScheme, "refresh_token"));
            Assert.Equal("access", await userManager.GetAuthenticationTokenAsync(user, authScheme, "access_token"));
        }
Exemple #2
0
        /// <summary>
        /// Tries to validate a token on the current request
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            _logger.LogTrace("HandleAuthenticateAsync called");

            var jwtScheme           = Scheme.Name + IdentityServerReferenceTokenAuthenticationDefaults.JwtAuthenticationScheme;
            var introspectionScheme = Scheme.Name + IdentityServerReferenceTokenAuthenticationDefaults.IntrospectionAuthenticationScheme;

            var  token       = Options.TokenRetriever(Context.Request);
            bool removeToken = false;

            try
            {
                if (token != null)
                {
                    _logger.LogTrace("Token found: {token}", token);

                    removeToken = true;
                    Context.Items.Add(IdentityServerReferenceTokenAuthenticationDefaults.TokenItemsKey, token);

                    // seems to be a JWT
                    if (token.Contains('.') && Options.SupportsJwt)
                    {
                        _logger.LogTrace("Token is a JWT and is supported.");


                        Context.Items.Add(IdentityServerReferenceTokenAuthenticationDefaults.EffectiveSchemeKey + Scheme.Name,
                                          jwtScheme);
                        return(await Context.AuthenticateAsync(jwtScheme));
                    }
                    else if (Options.SupportsIntrospection)
                    {
                        _logger.LogTrace("Token is a reference token and is supported.");

                        Context.Items.Add(IdentityServerReferenceTokenAuthenticationDefaults.EffectiveSchemeKey + Scheme.Name,
                                          introspectionScheme);
                        var authenticationResult = await Context.AuthenticateAsync(introspectionScheme);

                        if (authenticationResult.Succeeded)
                        {
                            await _userHandler.Handle(authenticationResult.Principal);
                        }

                        return(authenticationResult);
                    }
                    else
                    {
                        _logger.LogTrace(
                            "Neither JWT nor reference tokens seem to be correctly configured for incoming token.");
                    }
                }

                // set the default challenge handler to JwtBearer if supported
                if (Options.SupportsJwt)
                {
                    Context.Items.Add(IdentityServerReferenceTokenAuthenticationDefaults.EffectiveSchemeKey + Scheme.Name, jwtScheme);
                }

                return(AuthenticateResult.NoResult());
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
                return(AuthenticateResult.Fail(ex));
            }
            finally
            {
                if (removeToken)
                {
                    Context.Items.Remove(IdentityServerReferenceTokenAuthenticationDefaults.TokenItemsKey);
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options.
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string token = null;

            try
            {
                // Give application opportunity to find from a different location, adjust, or reject token
                var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options);

                // event can set the token
                await Events.MessageReceived(messageReceivedContext);

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

                // If application retrieved token from somewhere else, use that.
                token = messageReceivedContext.Token;

                if (string.IsNullOrEmpty(token))
                {
                    string authorization = Request.Headers[HeaderNames.Authorization];

                    // If no authorization header found, nothing to process further
                    if (string.IsNullOrEmpty(authorization))
                    {
                        return(AuthenticateResult.NoResult());
                    }

                    if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        token = authorization.Substring("Bearer ".Length).Trim();
                    }

                    // If no token found, no further work possible
                    if (string.IsNullOrEmpty(token))
                    {
                        return(AuthenticateResult.NoResult());
                    }
                }

                var currentConfiguration = await this.dynamicJwtBearerHanderConfigurationResolver.ResolveCurrentOpenIdConfiguration(Context);

                var validationParameters = Options.TokenValidationParameters.Clone();
                if (currentConfiguration != null)
                {
                    var issuers = new[] { currentConfiguration.Issuer };
                    validationParameters.ValidIssuers = validationParameters.ValidIssuers?.Concat(issuers) ?? issuers;

                    validationParameters.IssuerSigningKeys = validationParameters.IssuerSigningKeys?.Concat(currentConfiguration.SigningKeys)
                                                             ?? currentConfiguration.SigningKeys;
                }

                List <Exception> validationFailures = null;
                SecurityToken    validatedToken;
                foreach (var validator in Options.SecurityTokenValidators)
                {
                    if (validator.CanReadToken(token))
                    {
                        ClaimsPrincipal principal;
                        try
                        {
                            principal = validator.ValidateToken(token, validationParameters, out validatedToken);
                        }
                        catch (Exception ex)
                        {
                            Logger.TokenValidationFailed(ex);

                            // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the event.
                            if (Options.RefreshOnIssuerKeyNotFound && Options.ConfigurationManager != null &&
                                ex is SecurityTokenSignatureKeyNotFoundException)
                            {
                                Options.ConfigurationManager.RequestRefresh();
                            }

                            if (validationFailures == null)
                            {
                                validationFailures = new List <Exception>(1);
                            }
                            validationFailures.Add(ex);
                            continue;
                        }

                        Logger.TokenValidationSucceeded();

                        var tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options)
                        {
                            Principal     = principal,
                            SecurityToken = validatedToken
                        };

                        await Events.TokenValidated(tokenValidatedContext);

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

                        if (Options.SaveToken)
                        {
                            tokenValidatedContext.Properties.StoreTokens(new[]
                            {
                                new AuthenticationToken {
                                    Name = "access_token", Value = token
                                }
                            });
                        }

                        tokenValidatedContext.Success();
                        return(tokenValidatedContext.Result);
                    }
                }

                if (validationFailures != null)
                {
                    var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                    {
                        Exception = (validationFailures.Count == 1) ? validationFailures[0] : new AggregateException(validationFailures)
                    };

                    await Events.AuthenticationFailed(authenticationFailedContext);

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

                    return(AuthenticateResult.Fail(authenticationFailedContext.Exception));
                }

                return(AuthenticateResult.Fail("No SecurityTokenValidator available for token: " + token ?? "[null]"));
            }
            catch (Exception ex)
            {
                Logger.ErrorProcessingMessage(ex);

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

                await Events.AuthenticationFailed(authenticationFailedContext);

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

                throw;
            }
        }
Exemple #4
0
 protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
 {
     if (!HasHMACAuthorizationHeader(Request))
     {
         return(AuthenticateResult.NoResult());
     }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string authorizationHeader = Request.Headers["Authorization"];

            if (string.IsNullOrEmpty(authorizationHeader))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!authorizationHeader.StartsWith(_Scheme + ' ', StringComparison.OrdinalIgnoreCase))
            {
                return(AuthenticateResult.NoResult());
            }

            string encodedCredentials = authorizationHeader.Substring(_Scheme.Length).Trim();

            if (string.IsNullOrEmpty(encodedCredentials))
            {
                const string noCredentialsMessage = "No credentials";
                Logger.LogInformation(noCredentialsMessage);
                return(AuthenticateResult.Fail(noCredentialsMessage));
            }

            try
            {
                string decodedCredentials = string.Empty;
                try
                {
                    decodedCredentials = Encoding.UTF8.GetString(Convert.FromBase64String(encodedCredentials));
                }
                catch (Exception ex)
                {
                    throw new Exception($"Failed to decode credentials : {encodedCredentials}", ex);
                }

                var delimiterIndex = decodedCredentials.IndexOf(':');
                if (delimiterIndex == -1)
                {
                    const string missingDelimiterMessage = "Invalid credentials, missing delimiter.";
                    Logger.LogInformation(missingDelimiterMessage);
                    return(AuthenticateResult.Fail(missingDelimiterMessage));
                }

                var username = decodedCredentials.Substring(0, delimiterIndex);
                var password = decodedCredentials.Substring(delimiterIndex + 1);

                var validateCredentialsContext = new ValidateCredentialsContext(Context, Scheme, Options)
                {
                    Username = username,
                    Password = password
                };

                await Options.Events.ValidateCredentials(validateCredentialsContext);

                if (validateCredentialsContext.Result != null)
                {
                    var ticket = new AuthenticationTicket(validateCredentialsContext.Principal, Scheme.Name);
                    return(AuthenticateResult.Success(ticket));
                }

                return(AuthenticateResult.NoResult());
            }
            catch (Exception ex)
            {
                var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex
                };

                await Options.Events.AuthenticationFailed(authenticationFailedContext);

                if (authenticationFailedContext.Result.Succeeded)
                {
                    return(AuthenticateResult.Success(authenticationFailedContext.Result.Ticket));
                }

                if (authenticationFailedContext.Result.None)
                {
                    return(AuthenticateResult.NoResult());
                }

                throw;
            }
        }
        public async Task <AuthenticationResult> GetAuthenticationResultAsync(AuthenticationHeaderValue authHeader)
        {
            ApiClientDetails apiClientDetails;

            try
            {
                // If there are credentials but the filter does not recognize the authentication scheme, do nothing.
                if (!authHeader.Scheme.EqualsIgnoreCase(AuthenticationScheme))
                {
                    _logger.Debug("Unknown auth header scheme");
                    return(new AuthenticationResult {
                        AuthenticateResult = AuthenticateResult.NoResult()
                    });
                }

                // If the credentials are bad, set the error result.
                if (string.IsNullOrEmpty(authHeader.Parameter))
                {
                    _logger.Debug("Missing auth header parameter");

                    return(new AuthenticationResult
                    {
                        AuthenticateResult = AuthenticateResult.Fail("Missing auth header parameter")
                    });
                }

                // If there are credentials that the filter understands, try to validate them.
                apiClientDetails = await _oAuthTokenValidator.GetClientDetailsForTokenAsync(authHeader.Parameter);
            }
            catch (Exception e)
            {
                _logger.Error(e);
                return(new AuthenticationResult {
                    AuthenticateResult = AuthenticateResult.Fail("Invalid Authorization Header")
                });
            }

            if (_expectedUseSandboxValue.Value.HasValue &&
                apiClientDetails.IsSandboxClient != _expectedUseSandboxValue.Value.Value)
            {
                string message = apiClientDetails.IsSandboxClient
                    ? "Sandbox credentials used in call to Production API"
                    : "Production credentials used in call to Sandbox API";

                return(new AuthenticationResult {
                    AuthenticateResult = AuthenticateResult.Fail(message)
                });
            }

            var identity = _claimsIdentityProvider.GetClaimsIdentity(
                apiClientDetails.EducationOrganizationIds,
                apiClientDetails.ClaimSetName,
                apiClientDetails.NamespacePrefixes,
                apiClientDetails.Profiles.ToList());

            var apiKeyContext = new ApiKeyContext(
                apiClientDetails.ApiKey,
                apiClientDetails.ClaimSetName,
                apiClientDetails.EducationOrganizationIds,
                apiClientDetails.NamespacePrefixes,
                apiClientDetails.Profiles,
                apiClientDetails.StudentIdentificationSystemDescriptor,
                apiClientDetails.CreatorOwnershipTokenId,
                apiClientDetails.OwnershipTokenIds);

            return(new AuthenticationResult
            {
                ClaimsIdentity = identity,
                ApiKeyContext = apiKeyContext
            });
        }
        /// <summary>
        /// Process Authentication Request
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            // get siteminder headers
            _logger.LogDebug("Parsing the HTTP headers for SiteMinder authentication credential");

            SiteMinderAuthOptions options = new SiteMinderAuthOptions();
            bool isDeveloperLogin         = false;
            bool isBCSCDeveloperLogin     = false;

            try
            {
                ClaimsPrincipal principal;
                HttpContext     context         = Request.HttpContext;
                IDynamicsClient _dynamicsClient = (IDynamicsClient)context.RequestServices.GetService(typeof(IDynamicsClient));

                IHostingEnvironment hostingEnv = (IHostingEnvironment)context.RequestServices.GetService(typeof(IHostingEnvironment));

                UserSettings userSettings = new UserSettings();

                string userId                 = null;
                string devCompanyId           = null;
                string siteMinderGuid         = "";
                string siteMinderBusinessGuid = "";
                string siteMinderUserType     = "";

                // **************************************************
                // If this is an Error or Authentiation API - Ignore
                // **************************************************
                string url = context.Request.GetDisplayUrl().ToLower();

                if (url.Contains(".js"))
                {
                    return(AuthenticateResult.NoResult());
                }

                // **************************************************
                // Check if we have a Dev Environment Cookie
                // **************************************************
                //if (!hostingEnv.IsProduction())
                //{
                // check for a fake BCeID login in dev mode
                string temp = context.Request.Cookies[options.DevAuthenticationTokenKey];

                if (string.IsNullOrEmpty(temp))     // could be an automated test user.
                {
                    temp = context.Request.Headers["DEV-USER"];
                }

                if (!string.IsNullOrEmpty(temp))
                {
                    if (temp.Contains("::"))
                    {
                        var temp2 = temp.Split("::");
                        userId = temp2[0];
                        if (temp2.Length >= 2)
                        {
                            devCompanyId = temp2[1];
                        }
                        else
                        {
                            devCompanyId = temp2[0];
                        }
                    }
                    else
                    {
                        userId       = temp;
                        devCompanyId = temp;
                    }
                    isDeveloperLogin = true;

                    _logger.LogDebug("Got user from dev cookie = " + userId + ", company = " + devCompanyId);
                }
                else
                {
                    // same set of tests for a BC Services Card dev login
                    temp = context.Request.Cookies[options.DevBCSCAuthenticationTokenKey];

                    if (string.IsNullOrEmpty(temp))     // could be an automated test user.
                    {
                        temp = context.Request.Headers["DEV-BCSC-USER"];
                    }

                    if (!string.IsNullOrEmpty(temp))
                    {
                        userId = temp;
                        isBCSCDeveloperLogin = true;

                        _logger.LogDebug("Got user from dev cookie = " + userId);
                    }
                }
                //}

                // **************************************************
                // Check if the user session is already created
                // **************************************************
                try
                {
                    _logger.LogInformation("Checking user session");
                    userSettings = UserSettings.ReadUserSettings(context);
                    _logger.LogDebug("UserSettings found: " + userSettings.GetJson());
                }
                catch
                {
                    //do nothing
                    _logger.LogDebug("No UserSettings found");
                }

                // is user authenticated - if so we're done
                if ((userSettings.UserAuthenticated && string.IsNullOrEmpty(userId)) ||
                    (userSettings.UserAuthenticated && !string.IsNullOrEmpty(userId) &&
                     !string.IsNullOrEmpty(userSettings.UserId) && userSettings.UserId == userId))
                {
                    _logger.LogDebug("User already authenticated with active session: " + userSettings.UserId);
                    principal = userSettings.AuthenticatedUser.ToClaimsPrincipal(options.Scheme, userSettings.UserType);
                    return(AuthenticateResult.Success(new AuthenticationTicket(principal, null, Options.Scheme)));
                }

                string smgov_userdisplayname = context.Request.Headers["smgov_userdisplayname"];
                if (!string.IsNullOrEmpty(smgov_userdisplayname))
                {
                    userSettings.UserDisplayName = smgov_userdisplayname;
                }

                string smgov_businesslegalname = context.Request.Headers["smgov_businesslegalname"];
                if (!string.IsNullOrEmpty(smgov_businesslegalname))
                {
                    userSettings.BusinessLegalName = smgov_businesslegalname;
                }

                // **************************************************
                // Authenticate based on SiteMinder Headers
                // **************************************************
                _logger.LogDebug("Parsing the HTTP headers for SiteMinder authentication credential");

                // At this point userID would only be set if we are logging in through as a DEV user

                if (string.IsNullOrEmpty(userId))
                {
                    _logger.LogDebug("Getting user data from headers");

                    userId = context.Request.Headers[options.SiteMinderUserNameKey];
                    if (string.IsNullOrEmpty(userId))
                    {
                        userId = context.Request.Headers[options.SiteMinderUniversalIdKey];
                    }

                    siteMinderGuid         = context.Request.Headers[options.SiteMinderUserGuidKey];
                    siteMinderBusinessGuid = context.Request.Headers[options.SiteMinderBusinessGuidKey];
                    siteMinderUserType     = context.Request.Headers[options.SiteMinderUserTypeKey];


                    // **************************************************
                    // Validate credentials
                    // **************************************************
                    if (string.IsNullOrEmpty(userId))
                    {
                        _logger.LogDebug(options.MissingSiteMinderUserIdError);
                        return(AuthenticateResult.Fail(options.MissingSiteMinderGuidError));
                    }

                    if (string.IsNullOrEmpty(siteMinderGuid))
                    {
                        _logger.LogDebug(options.MissingSiteMinderGuidError);
                        return(AuthenticateResult.Fail(options.MissingSiteMinderGuidError));
                    }
                    if (string.IsNullOrEmpty(siteMinderUserType))
                    {
                        _logger.LogDebug(options.MissingSiteMinderUserTypeError);
                        return(AuthenticateResult.Fail(options.MissingSiteMinderUserTypeError));
                    }
                }
                else // DEV user, setup a fake session and SiteMinder headers.
                {
                    if (isDeveloperLogin && _dynamicsClient != null)
                    {
                        _logger.LogError("Generating a Development user");
                        userSettings.BusinessLegalName = devCompanyId + " BusinessProfileName";
                        userSettings.UserDisplayName   = userId + " BCeIDContactType";

                        // search for a matching user.
                        var existingContact = _dynamicsClient.GetContactByName(userId, "BCeIDContactType");

                        if (existingContact != null)
                        {
                            siteMinderGuid = existingContact.Externaluseridentifier;
                        }
                        else
                        {
                            siteMinderGuid = GuidUtility.CreateIdForDynamics("contact", userSettings.UserDisplayName).ToString();
                        }

                        var existingBusiness = await _dynamicsClient.GetAccountByLegalName(userSettings.BusinessLegalName);

                        if (existingBusiness != null)
                        {
                            siteMinderBusinessGuid = existingBusiness.BcgovBceid;
                        }
                        {
                            siteMinderBusinessGuid = GuidUtility.CreateIdForDynamics("account", userSettings.BusinessLegalName).ToString();
                        }
                        siteMinderUserType = "Business";
                    }
                    else if (isBCSCDeveloperLogin)
                    {
                        _logger.LogError("Generating a Development BC Services user");
                        userSettings.BusinessLegalName = null;
                        userSettings.UserDisplayName   = userId + " Associate";
                        siteMinderGuid         = GuidUtility.CreateIdForDynamics("bcsc", userSettings.UserDisplayName).ToString();
                        siteMinderBusinessGuid = null;
                        siteMinderUserType     = "VerifiedIndividual";
                    }
                }

                // Previously the code would do a database lookup here.  However there is no backing database for the users table now,
                // so we just do a Dynamics lookup on the siteMinderGuid.

                _logger.LogDebug("Loading user external id = " + siteMinderGuid);
                if (_dynamicsClient != null)
                {
                    userSettings.AuthenticatedUser = await _dynamicsClient.LoadUser(siteMinderGuid, context.Request.Headers, _logger);
                }

                _logger.LogDebug("After getting authenticated user = "******" (" + userId + ")");
                    return(AuthenticateResult.Fail(options.InactivegDbUserIdError));
                }

                if (userSettings.AuthenticatedUser != null && !String.IsNullOrEmpty(siteMinderUserType))
                {
                    userSettings.AuthenticatedUser.UserType = siteMinderUserType;
                }
                userSettings.UserType = siteMinderUserType;

                // This line gets the various claims for the current user.
                ClaimsPrincipal userPrincipal = userSettings.AuthenticatedUser.ToClaimsPrincipal(options.Scheme, userSettings.UserType);

                // **************************************************
                // Create authenticated user
                // **************************************************
                _logger.LogDebug("Authentication successful: " + userId);
                _logger.LogDebug("Setting identity and creating session for: " + userId);

                // create session info for the current user
                userSettings.UserId                = userId;
                userSettings.UserAuthenticated     = true;
                userSettings.IsNewUserRegistration = (userSettings.AuthenticatedUser == null);

                // set other session info
                userSettings.SiteMinderGuid         = siteMinderGuid;
                userSettings.SiteMinderBusinessGuid = siteMinderBusinessGuid;
                _logger.LogDebug("Before getting contact and account ids = " + userSettings.GetJson());

                if (userSettings.AuthenticatedUser != null)
                {
                    userSettings.ContactId = userSettings.AuthenticatedUser.ContactId.ToString();

                    if (siteMinderBusinessGuid != null) // BCeID user
                    {
                        var account = await _dynamicsClient.GetAccountBySiteminderBusinessGuid(siteMinderBusinessGuid);

                        if (account != null && account.Accountid != null)
                        {
                            userSettings.AccountId = account.Accountid;
                            userSettings.AuthenticatedUser.AccountId = Guid.Parse(account.Accountid);
                        }
                    }
                }

                if (!hostingEnv.IsProduction() && (isDeveloperLogin || isBCSCDeveloperLogin))
                {
                    _logger.LogError("DEV MODE Setting identity and creating session for: " + userId);

                    if (isDeveloperLogin)
                    {
                        userSettings.BusinessLegalName = devCompanyId + " BusinessProfileName";
                        userSettings.UserDisplayName   = userId + " BCeIDContactType";

                        // add generated guids
                        userSettings.SiteMinderBusinessGuid = GuidUtility.CreateIdForDynamics("account", userSettings.BusinessLegalName).ToString();
                        userSettings.SiteMinderGuid         = GuidUtility.CreateIdForDynamics("contact", userSettings.UserDisplayName).ToString();
                    }
                    else if (isBCSCDeveloperLogin)
                    {
                        userSettings.BusinessLegalName = null;
                        userSettings.UserDisplayName   = userId + " Associate";

                        // add generated guids
                        userSettings.SiteMinderBusinessGuid = null;
                        userSettings.SiteMinderGuid         = GuidUtility.CreateIdForDynamics("bcsc", userSettings.UserDisplayName).ToString();
                    }

                    if (userSettings.IsNewUserRegistration)
                    {
                        if (isDeveloperLogin)
                        {
                            // add generated guids
                            userSettings.AccountId = userSettings.SiteMinderBusinessGuid;
                            userSettings.ContactId = userSettings.SiteMinderGuid;
                        }
                        else if (isBCSCDeveloperLogin)
                        {
                            // set to null for now
                            userSettings.AccountId = null;
                            userSettings.ContactId = null;
                        }

                        _logger.LogDebug("New user registration:" + userSettings.UserDisplayName);
                        _logger.LogDebug("userSettings.SiteMinderBusinessGuid:" + userSettings.SiteMinderBusinessGuid);
                        _logger.LogDebug("userSettings.SiteMinderGuid:" + userSettings.SiteMinderGuid);
                        _logger.LogDebug("userSettings.AccountId:" + userSettings.AccountId);
                        _logger.LogDebug("userSettings.ContactId:" + userSettings.ContactId);
                    }
                    // Set account ID from authenticated user
                    else if (userSettings.AuthenticatedUser != null)
                    {
                        // populate the business GUID.
                        if (string.IsNullOrEmpty(userSettings.AccountId))
                        {
                            userSettings.AccountId = userSettings.AuthenticatedUser.AccountId.ToString();
                        }
                        if (string.IsNullOrEmpty(userSettings.ContactId))
                        {
                            userSettings.ContactId = userSettings.AuthenticatedUser.ContactId.ToString();
                        }
                        _logger.LogDebug("Returning user:"******"userSettings.AccountId:" + userSettings.AccountId);
                        _logger.LogDebug("userSettings.ContactId:" + userSettings.ContactId);
                    }
                }

                // add the worker settings if it is a new user.
                if (userSettings.IsNewUserRegistration && userSettings.NewWorker == null)
                {
                    userSettings.NewWorker = new ViewModels.Worker();
                    userSettings.NewWorker.CopyHeaderValues(context.Request.Headers);
                }

                // add the worker settings if it is a new user.
                if (userSettings.IsNewUserRegistration && userSettings.NewContact == null)
                {
                    userSettings.NewContact = new ViewModels.Contact();
                    userSettings.NewContact.CopyHeaderValues(context.Request.Headers);
                }

                // **************************************************
                // Update user settings
                // **************************************************
                UserSettings.SaveUserSettings(userSettings, context);

                // done!
                principal = userPrincipal;
                return(AuthenticateResult.Success(new AuthenticationTicket(principal, null, Options.Scheme)));
            }
            catch (Exception exception)
            {
                _logger.LogError(exception.Message);
                Console.WriteLine(exception);
                throw;
            }
        }
Exemple #8
0
        /// <summary>
        /// <para>
        ///    Add Identity for authenticn. Note as of Auth 2.0, all types needed are regsitered
        ///    under AddAuthentication.
        ///</para>
        /// <para>
        ///  At this stage:
        ///    - use JWT (bearer) tokens
        ///    Currently, it is authenticated or not (no roles or claims)
        /// </para>
        /// <remarks>
        ///    see https://github.com/aspnet/Security/issues/1310
        /// </remarks>
        /// </summary>
        public static IServiceCollection AddAuthenticationWithJwtToken(
            this IServiceCollection services,
            IConfiguration configuration)
        {
            var api = configuration.GetSection(ApiDomainSettings.SectionName).Get <ApiDomainSettings>();

            // Needed, well documented as a problem
            // see https://github.com/aspnet/Security/issues/1043
            // see https://dev.to/coolgoose/setting-up-jwt-and-identity-authorizationauthentication-in-asp-net-core-4l45
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // => remove default claims

            var auth0 = configuration.GetSection(Auth0Configuration.SectionName).Get <Auth0Configuration>();

            var domain = $"https://{auth0.Domain}/";

            services
            .AddAuthentication(
                authenticationOptions =>
            {
                /**
                 * Authenticate using AuthenticationOptions.DefaultAuthenticateScheme to set httpContext.User
                 */
                authenticationOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                ;

                /**
                 * The default scheme to use with [Authorize] attributed methods.
                 *
                 * NOTE: if you can't get a Context.User, it is because you don't have an [Authorize] attribute
                 *       that loads up the User onto the context.
                 */
                authenticationOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

                /**
                 * The global overriding default when any of above and others are no set. Thereotically,
                 * this is not needed because the two above are set.
                 *
                 * Others that could be set see AuthenticationOptions
                 */
                authenticationOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            }
                )
            .AddJwtBearer(AuthenticatorDefaults.ExternalAuthenticationSchemeName, options =>
            {
                // see https://auth0.com/blog/securing-asp-dot-net-core-2-applications-with-jwts/
                //
                // As requested when creating it, our API will use RS256 as the algorithm for signing tokens.
                // Since RS256 uses a private/public key pair, it verifies the tokens against the
                // public key for our Auth0 account. The ASP.NET Core JWT middleware will handle downloading
                // the JSON Web Key Set (JWKS) file containing the public key for us, and will use that
                // to verify the access_token signature.
                options.Authority = domain;
                options.Audience  = auth0.Audience;


                // see https://www.jerriepelser.com/blog/accessing-tokens-aspnet-core-2/
                //
                // Set to true if you want to get the value of the access_token in one of your
                // controller actions, you will need to retrieve the AuthenticateInfo. The access_token
                // will be stored inside the Properties with the key “.Token.access_token”:
                //
                // eg for this scheme "JSONWebToken"
                //
                //    string accessToken = await HttpContext.GetTokenAsync("access_token");
                //

/*
 *                  options.SaveToken = true;
 */

                options.Challenge =
                    string.Format("{0} realm=\"{1}\" uri={2}",
                                  AuthenticatorDefaults.ExternalAuthenticationSchemeName,
                                  AuthenticatorDefaults.AuthenticatorAuth0Realm,
                                  api.AuthorizationUri());

                options.Events = new JwtBearerEvents
                {
                    /**
                     * Read a custom authorization header for scheme name: JSONWebToken
                     *
                     * example:
                     *    Authorization: JSONWebToken eyJ0eXAiOiJKV1QiLCJhbG...
                     *
                     * Default implementation is to look for scheme: Bearer (see https://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs#L63)
                     *
                     * This uses the event OnMessageReceived to process the header and pass it into the pipeline.
                     *   see event trigger: https://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication.JwtBearer/JwtBearerHandler.cs#L54
                     *
                     *
                     * see https://andrewlock.net/a-look-behind-the-jwt-bearer-authentication-middleware-in-asp-net-core/#readauthorizationheader
                     * related see https://stackoverflow.com/questions/41955117/custom-token-location-for-jwtbearermiddleware
                     */
                    OnMessageReceived = context =>
                    {
                        if (string.IsNullOrEmpty(context.Token))
                        {
                            string authorization = context.Request.Headers["Authorization"];

                            // If no authorization header found, nothing to process further
                            if (string.IsNullOrEmpty(authorization))
                            {
                                return(Task.FromResult(AuthenticateResult.NoResult()));
                            }

                            // note the space in the prefix
                            var schemePrefx = $"{AuthenticatorDefaults.ExternalAuthenticationSchemeName} ";
                            if (authorization.StartsWith(schemePrefx, StringComparison.OrdinalIgnoreCase))
                            {
                                // this then gets picked up further in the pipeline to be processes
                                context.Token = authorization.Substring(schemePrefx.Length).Trim();
                            }

                            // If no token found, no further work possible
                            if (string.IsNullOrEmpty(context.Token))
                            {
                                return(Task.FromResult(AuthenticateResult.NoResult()));
                            }
                        }

                        return(Task.CompletedTask);
                    },

                    /**
                     * Once a token has been validated (above) then add the user to the claims.
                     *
                     * The design is that matching the internal id requires a database request and will be
                     * required once per request. It is then cached and used through any actions.
                     *
                     * Checking Id:
                     *
                     *  User.Claims.FindFirst(c => c.Type == UserIdClaimKey).Value
                     */
                    OnTokenValidated = async context =>
                    {
                        // we need to hand in the context Principal at this point as it has not yet
                        // been loaded on the IHttpContextAssessor required for the UserResolverService
                        var user = await context.HttpContext.RequestServices
                                   .GetRequiredService <IUserResolverService>()
                                   .GetPrincipleUserAsync(context.Principal);

                        if (!user.Id.IsNullOrWhitespace())
                        {
                            context.Principal.AddIdentityIdToClaims(user.Id);
                        }
                    }
                };
            });

            return(services);
        }
Exemple #9
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            // You only get client certificates over HTTPS
            if (!Context.Request.IsHttps)
            {
                return(AuthenticateResult.NoResult());
            }

            var clientCertificate = await Context.Connection.GetClientCertificateAsync();

            // This should never be the case, as cert authentication happens long before ASP.NET kicks in.
            if (clientCertificate == null)
            {
                Logger.LogDebug("No client certificate found.");
                return(AuthenticateResult.NoResult());
            }

            // If we have a self signed cert, and they're not allowed, exit early and not bother with
            // any other validations.
            if (clientCertificate.IsSelfSigned() &&
                !Options.AllowedCertificateTypes.HasFlag(CertificateTypes.SelfSigned))
            {
                Logger.LogWarning("Self signed certificate rejected, subject was {0}", clientCertificate.Subject);

                return(AuthenticateResult.Fail("Options do not allow self signed certificates."));
            }

            // If we have a chained cert, and they're not allowed, exit early and not bother with
            // any other validations.
            if (!clientCertificate.IsSelfSigned() &&
                !Options.AllowedCertificateTypes.HasFlag(CertificateTypes.Chained))
            {
                Logger.LogWarning("Chained certificate rejected, subject was {0}", clientCertificate.Subject);

                return(AuthenticateResult.Fail("Options do not allow chained certificates."));
            }

            var chainPolicy = BuildChainPolicy(clientCertificate);

            try
            {
                var chain = new X509Chain
                {
                    ChainPolicy = chainPolicy
                };

                var certificateIsValid = chain.Build(clientCertificate);

                if (!certificateIsValid)
                {
                    using (Logger.BeginScope(clientCertificate.SHA256Thumprint()))
                    {
                        Logger.LogWarning("Client certificate failed validation, subject was {0}", clientCertificate.Subject);
                        foreach (var validationFailure in chain.ChainStatus)
                        {
                            Logger.LogWarning("{0} {1}", validationFailure.Status, validationFailure.StatusInformation);
                        }
                    }
                    return(AuthenticateResult.Fail("Client certificate failed validation."));
                }

                var validateCertificateContext = new ValidateCertificateContext(Context, Scheme, Options)
                {
                    ClientCertificate = clientCertificate
                };

                await Events.ValidateCertificate(validateCertificateContext);

                if (validateCertificateContext.Result != null &&
                    validateCertificateContext.Result.Succeeded)
                {
                    var ticket = new AuthenticationTicket(validateCertificateContext.Principal, Scheme.Name);
                    return(AuthenticateResult.Success(ticket));
                }

                if (validateCertificateContext.Result != null &&
                    validateCertificateContext.Result.Failure != null)
                {
                    return(AuthenticateResult.Fail(validateCertificateContext.Result.Failure));
                }

                return(AuthenticateResult.NoResult());
            }
            catch (Exception ex)
            {
                var authenticationFailedContext = new CertificateAuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex
                };

                await Events.AuthenticationFailed(authenticationFailedContext);

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

                throw;
            }
        }
        /// <summary>
        /// Process Authentication Request
        /// </summary>
        /// <returns></returns>
        protected override Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            // get siteminder headers
            _logger.LogDebug("Parsing the HTTP headers for SiteMinder authentication credential");

            SiteMinderAuthOptions options = new SiteMinderAuthOptions();

            try
            {
                ClaimsPrincipal principal;

                HttpContext         context    = Request.HttpContext;
                DataAccess          dataAccess = (DataAccess)context.RequestServices.GetService(typeof(DataAccess));
                IHostingEnvironment hostingEnv = (IHostingEnvironment)context.RequestServices.GetService(typeof(IHostingEnvironment));

                UserSettings userSettings   = new UserSettings();
                string       userId         = "";
                string       siteMinderGuid = "";

                // **************************************************
                // If this is an Error or Authentiation API - Ignore
                // **************************************************
                string url = context.Request.GetDisplayUrl().ToLower();

                if (url.Contains("/authentication/dev") ||
                    url.Contains("/error") ||
                    url.Contains(".map") ||
                    url.Contains(".js"))
                {
                    return(Task.FromResult(AuthenticateResult.NoResult()));
                }

                // **************************************************
                // Check if we have a Dev Environment Cookie
                // **************************************************
                if (hostingEnv.IsDevelopment())
                {
                    string temp = context.Request.Cookies[options.DevAuthenticationTokenKey];

                    if (!string.IsNullOrEmpty(temp))
                    {
                        userId = temp;
                    }
                }

                // **************************************************
                // Check if the user session is already created
                // **************************************************
                try
                {
                    _logger.LogInformation("Checking user session");
                    userSettings = UserSettings.ReadUserSettings(context);
                }
                catch
                {
                    //do nothing
                }

                // is user authenticated - if so we're done
                if ((userSettings.UserAuthenticated && string.IsNullOrEmpty(userId)) ||
                    (userSettings.UserAuthenticated && !string.IsNullOrEmpty(userId) &&
                     !string.IsNullOrEmpty(userSettings.UserId) && userSettings.UserId == userId))
                {
                    _logger.LogInformation("User already authenticated with active session: " + userSettings.UserId);
                    principal = userSettings.AuthenticatedUser.ToClaimsPrincipal(options.Scheme);
                    return(Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal, null, Options.Scheme))));
                }

                // **************************************************
                // Authenticate based on SiteMinder Headers
                // **************************************************
                _logger.LogDebug("Parsing the HTTP headers for SiteMinder authentication credential");

                if (string.IsNullOrEmpty(userId))
                {
                    userId = context.Request.Headers[options.SiteMinderUserNameKey];
                    if (string.IsNullOrEmpty(userId))
                    {
                        userId = context.Request.Headers[options.SiteMinderUniversalIdKey];
                    }

                    siteMinderGuid = context.Request.Headers[options.SiteMinderUserGuidKey];

                    // **************************************************
                    // Validate credentials
                    // **************************************************
                    if (string.IsNullOrEmpty(userId))
                    {
                        _logger.LogError(options.MissingSiteMinderUserIdError);
                        return(Task.FromResult(AuthenticateResult.Fail(options.MissingSiteMinderGuidError)));
                    }

                    if (string.IsNullOrEmpty(siteMinderGuid))
                    {
                        _logger.LogError(options.MissingSiteMinderGuidError);
                        return(Task.FromResult(AuthenticateResult.Fail(options.MissingSiteMinderGuidError)));
                    }
                }

                // **************************************************
                // Validate credential against database
                // **************************************************
                userSettings.AuthenticatedUser = hostingEnv.IsDevelopment()
                    ? dataAccess.LoadUser(userId)
                    : dataAccess.LoadUser(userId, siteMinderGuid);

                if (userSettings.AuthenticatedUser == null)
                {
                    _logger.LogWarning(options.MissingDbUserIdError + " (" + userId + ")");
                    return(Task.FromResult(AuthenticateResult.Fail(options.MissingDbUserIdError)));
                }

                if (!userSettings.AuthenticatedUser.Active)
                {
                    _logger.LogWarning(options.InactivegDbUserIdError + " (" + userId + ")");
                    return(Task.FromResult(AuthenticateResult.Fail(options.InactivegDbUserIdError)));
                }

                // **************************************************
                // Validate / check user permissions
                // **************************************************
                ClaimsPrincipal userPrincipal = userSettings.AuthenticatedUser.ToClaimsPrincipal(options.Scheme);

                if (!userPrincipal.HasClaim(User.PermissionClaim, Permission.Login)
                    )
                {
                    _logger.LogWarning("User does not have ");
                    return(Task.FromResult(AuthenticateResult.Fail(options.InvalidPermissions)));
                }

                // **************************************************
                // Create authenticated user
                // **************************************************
                _logger.LogInformation("Authentication successful: " + userId);
                _logger.LogInformation("Setting identity and creating session for: " + userId);

                // create session info
                userSettings.UserId            = userId;
                userSettings.UserAuthenticated = true;

                // **************************************************
                // Update user settings
                // **************************************************
                UserSettings.SaveUserSettings(userSettings, context);

                // done!
                principal = userPrincipal;
                return(Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(principal, null, Options.Scheme))));
            }
            catch (Exception exception)
            {
                _logger.LogError(exception.Message);
                Console.WriteLine(exception);
                throw;
            }
        }
        /// <summary>
        /// Tries to validate a token on the current request
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            _logger.LogTrace("HandleAuthenticateAsync called");

            if (!Context.Request.Headers.ContainsKey("x-authScheme"))
            {
                return(AuthenticateResult.NoResult());
            }

            var authScheme = Context.Request.Headers["x-authScheme"];

            if (string.IsNullOrWhiteSpace(authScheme))
            {
                return(AuthenticateResult.NoResult());
            }

            if (!Global.SchemeRecords.ContainsKey(authScheme))
            {
                return(AuthenticateResult.NoResult());
            }

            var jwtScheme = Scheme.Name + authScheme;


            var  token       = Options.TokenRetriever(Context.Request);
            bool removeToken = false;

            try
            {
                if (token != null)
                {
                    _logger.LogTrace("Token found: {token}", token);

                    removeToken = true;
                    Context.Items.Add(MultiAuthorityAuthenticationDefaults.TokenItemsKey, token);

                    // seems to be a JWT
                    if (token.Contains('.') && Options.SupportsJwt)
                    {
                        _logger.LogTrace("Token is a JWT and is supported.");


                        Context.Items.Add(MultiAuthorityAuthenticationDefaults.EffectiveSchemeKey + Scheme.Name, jwtScheme);
                        return(await Context.AuthenticateAsync(jwtScheme));
                    }

                    else
                    {
                        _logger.LogTrace("JWT token seem not to be correctly configured for incoming token.");
                    }
                }

                // set the default challenge handler to JwtBearer if supported
                if (Options.SupportsJwt)
                {
                    Context.Items.Add(MultiAuthorityAuthenticationDefaults.EffectiveSchemeKey + Scheme.Name, jwtScheme);
                }

                return(AuthenticateResult.NoResult());
            }
            finally
            {
                if (removeToken)
                {
                    Context.Items.Remove(MultiAuthorityAuthenticationDefaults.TokenItemsKey);
                }
            }
        }
Exemple #12
0
 public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
 {
     return(Task.FromResult(AuthenticateResult.NoResult()));
 }
Exemple #13
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var transaction = Context.Features.Get <OpenIddictServerAspNetCoreFeature>()?.Transaction ??
                              throw new InvalidOperationException("An unknown error occurred while retrieving the OpenIddict server context.");

            // Note: in many cases, the authentication token was already validated by the time this action is called
            // (generally later in the pipeline, when using the pass-through mode). To avoid having to re-validate it,
            // the authentication context is resolved from the transaction. If it's not available, a new one is created.
            var context = transaction.GetProperty <ProcessAuthenticationContext>(typeof(ProcessAuthenticationContext).FullName);

            if (context == null)
            {
                context = new ProcessAuthenticationContext(transaction);
                await _dispatcher.DispatchAsync(context);

                // Store the context object in the transaction so it can be later retrieved by handlers
                // that want to access the authentication result without triggering a new authentication flow.
                transaction.SetProperty(typeof(ProcessAuthenticationContext).FullName, context);
            }

            if (context.IsRequestHandled || context.IsRequestSkipped)
            {
                return(AuthenticateResult.NoResult());
            }

            else if (context.IsRejected)
            {
                // Note: the missing_token error is special-cased to indicate to ASP.NET Core
                // that no authentication result could be produced due to the lack of token.
                // This also helps reducing the logging noise when no token is specified.
                if (string.Equals(context.Error, Errors.MissingToken, StringComparison.Ordinal))
                {
                    return(AuthenticateResult.NoResult());
                }

                var properties = new AuthenticationProperties(new Dictionary <string, string>
                {
                    [OpenIddictServerAspNetCoreConstants.Properties.Error]            = context.Error,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = context.ErrorDescription,
                    [OpenIddictServerAspNetCoreConstants.Properties.ErrorUri]         = context.ErrorUri
                });

                return(AuthenticateResult.Fail("An error occurred while authenticating the current request.", properties));
            }

            else
            {
                // Store the token to allow any ASP.NET Core component (e.g a controller)
                // to retrieve it (e.g to make an API request to another application).
                var properties = new AuthenticationProperties();
                properties.StoreTokens(new[]
                {
                    new AuthenticationToken
                    {
                        Name  = context.TokenType,
                        Value = context.Token
                    }
                });

                return(AuthenticateResult.Success(new AuthenticationTicket(
                                                      context.Principal, properties,
                                                      OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)));
            }
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            if (!Request.Headers.ContainsKey("Authorization"))
            {
                return(AuthenticateResult.NoResult());
            }

            string token = null;

            string authorization = Request.Headers["Authorization"];

            // If no authorization header found, nothing to process further
            if (string.IsNullOrEmpty(authorization))
            {
                return(AuthenticateResult.NoResult());
            }

            if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
            {
                token = authorization.Substring("Bearer ".Length).Trim();
            }

            // If no token found, no further work possible
            if (string.IsNullOrEmpty(token))
            {
                return(AuthenticateResult.NoResult());
            }

            try
            {
                string result = await Options.UserInfoEndpoint.WithOAuthBearerToken(token)
                                .PostUrlEncodedAsync(new
                {
                    client_id     = Options.ClientId,
                    client_secret = Options.ClientSecret,
                })
                                .ReceiveString();

                JObject user = JObject.Parse(result);

                ICollection <Claim> claims = new List <Claim>();

                foreach (JProperty property in user.Properties().Select(x => x))
                {
                    if (!property.Value.Any())
                    {
                        claims.Add(new Claim(property.Name, (string)property.Value));
                    }
                    else
                    {
                        foreach (JToken jToken in property.Value)
                        {
                            claims.Add(new Claim(property.Name, (string)jToken));
                        }
                    }
                }

                ClaimsIdentity identity = new ClaimsIdentity(claims, "AuthenticationTypes.Federation");

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

                return(AuthenticateResult.Success(ticket));
            }
            catch (FlurlHttpException e)
            {
                return(AuthenticateResult.Fail(await e.GetResponseStringAsync()));
            }
        }
Exemple #15
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;
            }
        }
Exemple #16
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            bool isTokenFromCookie = false;

            try
            {
                Logger.LogDebug("HandleAuthenticateAsync: started authentication check...");
                string token = string.Empty;

                // check first for header
                if (!string.IsNullOrEmpty(Program.JwtHeader))
                {
                    var header = Request.Headers["Authorization"];
                    if (header.Count() > 0)
                    {
                        Logger.LogDebug($"HandleAuthenticateAsync: checking header named \"Authorization\" for token...");
                        token = header.First().Replace("Bearer ", "");
                    }
                }

                // look next at the cookie
                if (!string.IsNullOrEmpty(Program.JwtCookie))
                {
                    Logger.LogDebug($"HandleAuthenticateAsync: checking cookie named \"{Program.JwtCookie}\" for token...");
                    token             = Request.Cookies[Program.JwtCookie];
                    isTokenFromCookie = true;
                }

                // shortcut if there is no token
                if (string.IsNullOrEmpty(token))
                {
                    Logger.LogDebug("HandleAuthenticateAsync: no token was found.");
                    return(AuthenticateResult.NoResult());
                }

                // validate the token
                var jwt = await TokenValidator.ValidateToken(token);

                // propogate the claims (this overload uses uri-names and dedupes)
                var claims = new List <Claim>();
                foreach (var claim in jwt.Payload.Claims)
                {
                    claims.AddLong(claim.Type, claim.Value);
                }

                // build the identity, principal, and ticket
                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 e)
            {
                Logger.LogWarning(e, "HandleAuthenticateAsync: exception...");
                if (isTokenFromCookie)
                {
                    Response.Cookies.Delete(Program.JwtCookie);                    // revoke the cookie
                }
                return(AuthenticateResult.Fail(e));
            }
        }
        //public async Task<HttpContext> Authenticate(ClientContext clientContext, string authorization, string scheme) {

        //    var authenticationService = _serviceProvider.GetRequiredService<IAuthenticationService>();
        //    var ctx = new DefaultHttpContext();
        //    ctx.RequestServices = _serviceProvider;

        //    if (String.IsNullOrWhiteSpace(scheme)) {
        //        var defaultScheme = await _schemes.GetDefaultAuthenticateSchemeAsync();
        //        scheme = defaultScheme?.Name;
        //    }

        //    AuthenticateResult authenticateResult;

        //    if (clientContext.UserValidUntil < DateTime.Now) {

        //        if (!authorization.Contains(" ")) {
        //            authorization = $"Bearer {authorization}";
        //        }
        //        ctx.Request.Headers["Authorization"] = authorization;


        //        authenticateResult = await authenticationService.AuthenticateAsync(ctx, scheme);

        //    } else {
        //        var t = new AuthenticationTicket(clientContext.User, clientContext.User.Identity.AuthenticationType);
        //        authenticateResult = AuthenticateResult.Success(t);
        //    }
        //    ctx.User = authenticateResult.Principal;
        //    clientContext.SetPrincipal(ctx.User);
        //    return ctx;
        //}



        public async Task <PolicyAuthorizationResult> Authorize(ClientContext clientContext, string authorization, MethodInfo methodInfo)
        {
            var authorizeData = methodInfo.GetAuthorizeData();

            if (!authorizeData.Any())
            {
                return(PolicyAuthorizationResult.Success());
            }

            var authenticationService = _serviceProvider.GetRequiredService <IAuthenticationService>();
            var policyEvaluator       = _serviceProvider.GetRequiredService <IPolicyEvaluator>();
            var policyProvider        = _serviceProvider.GetRequiredService <IAuthorizationPolicyProvider>();


            if (!authorizeData.Any())
            {
                authorizeData = methodInfo.DeclaringType?.GetCustomAttributes <AuthorizeAttribute>().ToList() ?? new List <AuthorizeAttribute>();
            }



            var policy = await AuthorizationPolicy.CombineAsync(policyProvider, authorizeData);

            if (policy == null)
            {
                return(PolicyAuthorizationResult.Success());
            }

            var ctx = new DefaultHttpContext();

            ctx.RequestServices = _serviceProvider;

            AuthenticateResult authenticateResult = AuthenticateResult.NoResult();

            Console.WriteLine($"{clientContext.UserValidUntil} - {DateTime.Now}");
            if (clientContext.UserValidUntil < DateTime.Now)
            {
                if (!authorization.Contains(" "))
                {
                    authorization = $"Bearer {authorization}";
                }
                ctx.Request.Headers["Authorization"] = authorization;


                foreach (var policyAuthenticationScheme in policy.AuthenticationSchemes)
                {
                    authenticateResult = await authenticationService.AuthenticateAsync(ctx, policyAuthenticationScheme);

                    if (authenticateResult.Succeeded)
                    {
                        clientContext.SetPrincipal(authenticateResult.Principal);
                        break;
                    }
                }
            }
            else
            {
                var t = new AuthenticationTicket(clientContext.User, clientContext.User.Identity.AuthenticationType);
                authenticateResult = AuthenticateResult.Success(t);
            }

            ctx.User = authenticateResult.Principal;


            if (methodInfo.GetCustomAttribute <AllowAnonymousAttribute>() != null)
            {
                return(PolicyAuthorizationResult.Success());
            }

            var authorizeResult = await policyEvaluator.AuthorizeAsync(policy, authenticateResult, ctx, clientContext);



            return(authorizeResult);
        }
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string siteMinderUserGuidHeader = Request.Headers["SMGOV_USERGUID"];
            string siteMinderUserTypeHeader = Request.Headers["SMGOV_USERTYPE"];

            if (siteMinderUserGuidHeader == null || siteMinderUserTypeHeader == null)
            {
                return(AuthenticateResult.NoResult());
            }

            if (siteMinderUserTypeHeader != ValidSiteMinderUserType)
            {
                return(AuthenticateResult.Fail("Invalid SiteMinder UserType Header."));
            }

            var authenticatedBySiteMinderPreviously = Context.User.Identity.AuthenticationType == SiteMinder;
            var applicationCode = Context.User.ApplicationCode();
            var participantId   = Context.User.ParticipantId();
            var agencyCode      = Context.User.AgencyCode();
            var isSupremeUser   = Context.User.IsSupremeUser();

            if (!authenticatedBySiteMinderPreviously)
            {
                var request = new UserInfoRequest
                {
                    DeviceName          = Environment.MachineName,
                    DomainUserGuid      = siteMinderUserGuidHeader,
                    DomainUserId        = Request.Headers["SM_USER"],
                    IpAddress           = Request.Headers["X-Real-IP"],
                    TemporaryAccessGuid = ""
                };
                var jcUserInfo = await JCUserService.GetUserInfo(request);

                if (jcUserInfo == null)
                {
                    return(AuthenticateResult.Fail("Couldn't authenticate through JC-Interface."));
                }

                applicationCode = "SCV";
                participantId   = jcUserInfo.UserPartId;
                agencyCode      = jcUserInfo.UserDefaultAgencyCd;
                isSupremeUser   = true;
            }

            var claims = new[] {
                new Claim(CustomClaimTypes.ApplicationCode, applicationCode),
                new Claim(CustomClaimTypes.JcParticipantId, participantId),
                new Claim(CustomClaimTypes.JcAgencyCode, agencyCode),
                new Claim(CustomClaimTypes.IsSupremeUser, isSupremeUser.ToString())
            };
            var identity  = new ClaimsIdentity(claims, Scheme.Name);
            var principal = new ClaimsPrincipal(identity);

            if (!authenticatedBySiteMinderPreviously)
            {
                await Context.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
            }

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

            return(AuthenticateResult.Success(ticket));
        }
Exemple #19
0
 protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
 {
     return(await Task.FromResult(AuthenticateResult.NoResult()));
 }
Exemple #20
0
 public Task <AuthenticateResult> AuthenticateAsync()
 {
     return(Task.FromResult(AuthenticateResult.NoResult()));
 }
Exemple #21
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            async Task <AuthenticateResult> DeleteLongSessionAndLogout(long sessionId)
            {
                await userManager.DeleteLongSessionAsync(sessionId);

                jweService.MakeLogoutCookiesAndHeaders(Response);

                return(AuthenticateResult.NoResult());
            }

            AuthenticateResult Logout(string msg)
            {
                jweService.MakeLogoutCookiesAndHeaders(Response);

                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"\nLogout: {msg}\n");
                Console.ResetColor();

                return(AuthenticateResult.NoResult());
            }

            try
            {
                var cookie = Request.Cookies[TokenClaimNames.LongToken2CoockiName];

                if (cookie == null)
                {
                    return(AuthenticateResult.NoResult());
                }


                JwtSecurityToken jwtLongToken2 = jweService.ReadLong2Token(cookie);
                if (jwtLongToken2 == null)
                {
                    return(Logout("No Long2 cookie token"));
                }

                var longToken2db = jwtLongToken2.Claims.First(x => x.Type == TokenClaimNames.LongToken2Db).Value;

                SunClaimsPrincipal sunClaimsPrincipal;

                if (Request.Headers.TryGetValue(Headers.LongToken1HeaderName, out StringValues longToken1db))
                {
                    int userId = int.Parse(jwtLongToken2.Claims.First(x => x.Type == ClaimTypes.NameIdentifier).Value);

                    var longSessionToFind = new LongSession
                    {
                        UserId     = userId,
                        LongToken1 = longToken1db,
                        LongToken2 = longToken2db
                    };

                    var longSession = await userManager.FindLongSessionAsync(longSessionToFind);

                    if (longSession == null)
                    {
                        return(Logout("Session not found"));
                    }

                    sunClaimsPrincipal = await jweService.RenewSecurityTokensAsync(Context, userId, longSession);

                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("\nToken renews\n");
                    Console.ResetColor();
                }
                else
                {
                    string authorization = Request.Headers["Authorization"];

                    if (string.IsNullOrEmpty(authorization))
                    {
                        return(Logout("No Authorization header"));
                    }

                    string jwtShortToken = null;
                    if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        jwtShortToken = authorization.Substring("Bearer ".Length).Trim();
                    }

                    if (string.IsNullOrEmpty(jwtShortToken))
                    {
                        return(Logout("No Bearer in Authorization header"));
                    }


                    var claimsPrincipal = jweService.ReadShortToken(jwtShortToken);

                    string lat2ran_1 = jwtLongToken2.Claims.First(x => x.Type == TokenClaimNames.LongToken2Ran).Value;
                    string lat2ran_2 = claimsPrincipal.Claims.First(x => x.Type == TokenClaimNames.LongToken2Ran).Value;

                    long sessionId =
                        long.Parse(jwtLongToken2.Claims.First(x => x.Type == TokenClaimNames.SessionId).Value);

                    if (!string.Equals(lat2ran_1, lat2ran_2))
                    {
                        return(await DeleteLongSessionAndLogout(sessionId));
                    }

                    string lat2db = jwtLongToken2.Claims.First(x => x.Type == TokenClaimNames.LongToken2Db).Value;

                    sunClaimsPrincipal = new SunClaimsPrincipal(claimsPrincipal, rolesCache, sessionId, lat2db);
                }

                if (jweBlackListService.IsTokenInBlackList(sunClaimsPrincipal.LongToken2Db))
                {
                    return(await DeleteLongSessionAndLogout(sunClaimsPrincipal.SessionId));
                }

                if (sunClaimsPrincipal.Roles.ContainsKey(RoleNames.Banned))
                {
                    return(await DeleteLongSessionAndLogout(sunClaimsPrincipal.SessionId));
                }

                var authenticationTicket = new AuthenticationTicket(sunClaimsPrincipal, SunJwt.Scheme);
                return(AuthenticateResult.Success(authenticationTicket));
            }
            catch (Exception e)
            {
                return(Logout("Error " + e));
            }
        }
Exemple #22
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()
        {
            try
            {
                var messageReceivedContext = new MessageReceivedContext(this.Context, this.Scheme, this.Options);

                await this.Events.MessageReceived(messageReceivedContext);

                string apiKey = messageReceivedContext.ApiKey;

                if (string.IsNullOrEmpty(apiKey))
                {
                    string header = this.Request.Headers[this.Options.Header];

                    if (string.IsNullOrEmpty(header))
                    {
                        this.Logger.ApiKeyValidationFailed();

                        return(AuthenticateResult.NoResult());
                    }

                    if (header.StartsWith(this.Options.HeaderKey, StringComparison.OrdinalIgnoreCase))
                    {
                        apiKey = header.Substring(this.Options.HeaderKey.Length).Trim();

                        var validateApiKeyContext = new ApiKeyValidatedContext(this.Context, this.Scheme, this.Options)
                        {
                            ApiKey    = apiKey,
                            Principal = new ClaimsPrincipal()
                        };

                        await this.Events.ApiKeyValidated(validateApiKeyContext);

                        if (validateApiKeyContext.Result != null)
                        {
                            this.Logger.ApiKeyValidationSucceeded();

                            return(validateApiKeyContext.Result);
                        }
                    }
                }

                this.Logger.ApiKeyValidationFailed();

                return(AuthenticateResult.NoResult());
            }
            catch (Exception ex)
            {
                this.Logger.ErrorProcessingMessage(ex);

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

                await this.Events.AuthenticationFailed(authenticationFailedContext);

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

                throw;
            }
        }
Exemple #24
0
        /// <summary>
        /// Tries to authenticate a reference token on the current request
        /// </summary>
        /// <returns></returns>
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            string token = Options.TokenRetriever(Context.Request);

            if (token.IsMissing())
            {
                return(AuthenticateResult.NoResult());
            }

            if (token.Contains('.') && Options.SkipTokensWithDots)
            {
                _logger.LogTrace("Token contains a dot - skipped because SkipTokensWithDots is set.");
                return(AuthenticateResult.NoResult());
            }

            if (Options.EnableCaching)
            {
                var claims = await _cache.GetClaimsAsync(token).ConfigureAwait(false);

                if (claims != null)
                {
                    var ticket = CreateTicket(claims);

                    _logger.LogTrace("Token found in cache.");

                    if (Options.SaveToken)
                    {
                        ticket.Properties.StoreTokens(new[]
                        {
                            new AuthenticationToken {
                                Name = "access_token", Value = token
                            }
                        });
                    }

                    return(AuthenticateResult.Success(ticket));
                }

                _logger.LogTrace("Token is not cached.");
            }

            // Use a LazyAsync to ensure only one thread is requesting introspection for a token - the rest will wait for the result
            var lazyIntrospection = Options.LazyIntrospections.GetOrAdd(token, CreateLazyIntrospection);

            try
            {
                var response = await lazyIntrospection.Value.ConfigureAwait(false);

                if (response.IsError)
                {
                    _logger.LogError("Error returned from introspection endpoint: " + response.Error);
                    return(AuthenticateResult.Fail("Error returned from introspection endpoint: " + response.Error));
                }

                if (response.IsActive)
                {
                    var ticket = CreateTicket(response.Claims);

                    if (Options.SaveToken)
                    {
                        ticket.Properties.StoreTokens(new[]
                        {
                            new AuthenticationToken {
                                Name = "access_token", Value = token
                            }
                        });
                    }

                    if (Options.EnableCaching)
                    {
                        await _cache.SetClaimsAsync(token, response.Claims, Options.CacheDuration, _logger).ConfigureAwait(false);
                    }

                    return(AuthenticateResult.Success(ticket));
                }
                else
                {
                    return(AuthenticateResult.Fail("Token is not active."));
                }
            }
            finally
            {
                // If caching is on and it succeeded, the claims are now in the cache.
                // If caching is off and it succeeded, the claims will be discarded.
                // Either way, we want to remove the temporary store of claims for this token because it is only intended for de-duping fetch requests
                Options.LazyIntrospections.TryRemove(token, out _);
            }
        }
Exemple #25
0
        protected override async Task <AuthenticateResult> HandleAuthenticateAsync()
        {
            var events = Events as BasicEvents;

            try {
                // .NET Core as of 2.0 does not support HTTP auth on sockets
                // This is alternative solution to anonymous access in SessionController.GetPipe()
                // but it only works for local connections (which may be OK for VSC but it won't work
                // in VSC with remote or Docker containers.

                //if (Uri.TryCreate(CurrentUri, UriKind.Absolute, out var uri)) {
                //    if (uri.IsLoopback && !Request.IsHttps) {
                //        var claims = new[] {
                //            new Claim(ClaimTypes.Name, "RTVS"),
                //            new Claim(Claims.RUser, string.Empty),
                //        };
                //        var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, BasicDefaults.AuthenticationScheme));
                //        var t = new AuthenticationTicket(principal, new AuthenticationProperties(), Scheme.Name);
                //        return AuthenticateResult.Success(t);
                //    }
                //}

                // retrieve authorization header
                string authorization = Request.Headers[HeaderNames.Authorization];

                if (string.IsNullOrEmpty(authorization))
                {
                    return(AuthenticateResult.NoResult());
                }

                if (!authorization.StartsWith(RequestHeaderPrefix, StringComparison.OrdinalIgnoreCase))
                {
                    return(AuthenticateResult.NoResult());
                }

                // retrieve credentials from header
                var encodedCredentials = authorization.Substring(RequestHeaderPrefix.Length);
                var decodedCredentials = default(string);
                try {
                    decodedCredentials = Encoding.UTF8.GetString(Convert.FromBase64String(encodedCredentials));
                } catch (Exception) {
                    return(AuthenticateResult.Fail("Invalid basic authentication header encoding."));
                }

                var index = decodedCredentials.IndexOf(':');
                if (index == -1)
                {
                    return(AuthenticateResult.Fail("Invalid basic authentication header format."));
                }

                var username      = decodedCredentials.Substring(0, index);
                var password      = decodedCredentials.Substring(index + 1);
                var signInContext = new BasicSignInContext(Context, Scheme, Options)
                {
                    Username = username,
                    Password = password,
                };

                await events.SignIn(signInContext);

                if (signInContext.Principal == null)
                {
                    return(AuthenticateResult.Fail("Invalid basic authentication credentials."));
                }

                var ticket = new AuthenticationTicket(signInContext.Principal, new AuthenticationProperties(), Scheme.Name);

                return(AuthenticateResult.Success(ticket));
            } catch (Exception ex) {
                var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options)
                {
                    Exception = ex,
                };

                await events.AuthenticationFailed(authenticationFailedContext);

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

                throw;
            }
        }
 public Task <AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
 {
     return(Task.FromResult(AuthenticateResult.NoResult()));
 }
 public Task <AuthenticateResult> AuthenticateAsync() => Task.FromResult(AuthenticateResult.NoResult());
        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")));
            }
        }
Exemple #29
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)));
        }
        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")));
            }
        }