public async Task LoginAsync(OpenidConnectPkceSettings openidClientPkceSettings = null)
        {
            try
            {
                openidClientPkceSettings = openidClientPkceSettings ?? globalOpenidClientPkceSettings;

                var nonce        = RandomGenerator.GenerateNonce();
                var codeVerifier = RandomGenerator.Generate(64);

                ValidateResponseMode(openidClientPkceSettings.ResponseMode);
                var loginCallBackUri = new Uri(new Uri(navigationManager.BaseUri), openidClientPkceSettings.LoginCallBackPath).OriginalString;
                var state            = await SaveStateAsync(openidClientPkceSettings, loginCallBackUri, navigationManager.Uri, codeVerifier : codeVerifier, nonce : nonce);

                var authenticationRequest = new AuthenticationRequest
                {
                    ClientId     = openidClientPkceSettings.ClientId,
                    ResponseMode = openidClientPkceSettings.ResponseMode,
                    ResponseType = openidClientPkceSettings.ResponseType,
                    RedirectUri  = loginCallBackUri,
                    Scope        = openidClientPkceSettings.AllScope.ToSpaceList(),
                    Nonce        = nonce,
                    State        = state
                };
                var codeChallengeRequest = new CodeChallengeSecret
                {
                    CodeChallenge       = await codeVerifier.Sha256HashBase64urlEncodedAsync(),
                    CodeChallengeMethod = IdentityConstants.CodeChallengeMethods.S256,
                };

                var requestDictionary = authenticationRequest.ToDictionary().AddToDictionary(codeChallengeRequest);
                if (openidClientPkceSettings.Resources?.Count() > 0)
                {
                    var resourceRequest = new ResourceRequest
                    {
                        Resources = openidClientPkceSettings.Resources
                    };
                    requestDictionary = requestDictionary.AddToDictionary(resourceRequest);
                }

                var oidcDiscovery = await GetOidcDiscoveryAsync(openidClientPkceSettings.OidcDiscoveryUri);

                var authorizationUri = QueryHelpers.AddQueryString(oidcDiscovery.AuthorizationEndpoint, requestDictionary);
                navigationManager.NavigateTo(authorizationUri, true);
            }
            catch (Exception ex)
            {
                throw new SecurityException($"Failed to login, Authority '{openidClientPkceSettings.Authority}'.", ex);
            }
        }
        //[InlineData("https://someapi.com/", "https://someapi.com/")]
        public void Test1(params string[] resources)
        {
            var authenticationRequest = new AuthenticationRequest
            {
                ClientId     = "clientx",
                ResponseMode = IdentityConstants.ResponseModes.FormPost,
                ResponseType = IdentityConstants.ResponseTypes.Code,
                RedirectUri  = "https://sometest.com",
                Scope        = "somescope",
                Nonce        = "xxx",
                State        = "xxx"
            };

            var resourceRequest = new ResourceRequest
            {
                Resources = resources
            };

            resourceRequest.Validate();

            var nameValueCollection = authenticationRequest.ToDictionary().AddToDictionary(resourceRequest);

            Assert.Equal(7 + resources.Count(), nameValueCollection.Count);
        }
Example #3
0
        public async Task <IActionResult> AuthenticationRequestAsync(string partyId)
        {
            logger.ScopeTrace(() => "Up, OIDC Authentication request.");
            var oidcUpSequenceData = await sequenceLogic.GetSequenceDataAsync <OidcUpSequenceData>(remove : false);

            if (!oidcUpSequenceData.UpPartyId.Equals(partyId, StringComparison.Ordinal))
            {
                throw new Exception("Invalid up-party id.");
            }
            logger.SetScopeProperty(Constants.Logs.UpPartyId, oidcUpSequenceData.UpPartyId);

            var party = await tenantRepository.GetAsync <TParty>(oidcUpSequenceData.UpPartyId);

            logger.SetScopeProperty(Constants.Logs.UpPartyClientId, party.Client.ClientId);

            await oidcDiscoveryReadUpLogic.CheckOidcDiscoveryAndUpdatePartyAsync(party);

            var nonce            = RandomGenerator.GenerateNonce();
            var loginCallBackUrl = HttpContext.GetUpPartyUrl(party.Name, Constants.Routes.OAuthController, Constants.Endpoints.AuthorizationResponse, partyBindingPattern: party.PartyBindingPattern);

            oidcUpSequenceData.ClientId    = !party.Client.SpClientId.IsNullOrWhiteSpace() ? party.Client.SpClientId : party.Client.ClientId;
            oidcUpSequenceData.RedirectUri = loginCallBackUrl;
            oidcUpSequenceData.Nonce       = nonce;
            if (party.Client.EnablePkce)
            {
                var codeVerifier = RandomGenerator.Generate(64);
                oidcUpSequenceData.CodeVerifier = codeVerifier;
            }
            await sequenceLogic.SaveSequenceDataAsync(oidcUpSequenceData);

            var authenticationRequest = new AuthenticationRequest
            {
                ClientId     = oidcUpSequenceData.ClientId,
                ResponseMode = party.Client.ResponseMode,
                ResponseType = party.Client.ResponseType,
                RedirectUri  = loginCallBackUrl,
                Nonce        = nonce,
                State        = await sequenceLogic.CreateExternalSequenceIdAsync()
            };

            switch (oidcUpSequenceData.LoginAction)
            {
            case LoginAction.ReadSession:
                authenticationRequest.Prompt = IdentityConstants.AuthorizationServerPrompt.None;
                break;

            case LoginAction.RequireLogin:
                authenticationRequest.Prompt = IdentityConstants.AuthorizationServerPrompt.Login;
                break;

            default:
                break;
            }

            if (oidcUpSequenceData.MaxAge.HasValue)
            {
                authenticationRequest.MaxAge = oidcUpSequenceData.MaxAge;
            }

            if (!oidcUpSequenceData.UserId.IsNullOrEmpty())
            {
                authenticationRequest.LoginHint = oidcUpSequenceData.UserId;
            }

            authenticationRequest.Scope = new[] { IdentityConstants.DefaultOidcScopes.OpenId }.ConcatOnce(party.Client.Scopes).ToSpaceList();

            //TODO add AcrValues
            //authenticationRequest.AcrValues = "urn:federation:authentication:windows";

            logger.ScopeTrace(() => $"Up, Authentication request '{authenticationRequest.ToJsonIndented()}'.", traceType: TraceTypes.Message);
            var nameValueCollection = authenticationRequest.ToDictionary();

            if (party.Client.EnablePkce)
            {
                var codeChallengeRequest = new CodeChallengeSecret
                {
                    CodeChallenge       = await oidcUpSequenceData.CodeVerifier.Sha256HashBase64urlEncodedAsync(),
                    CodeChallengeMethod = IdentityConstants.CodeChallengeMethods.S256,
                };

                logger.ScopeTrace(() => $"Up, CodeChallengeSecret request '{codeChallengeRequest.ToJsonIndented()}'.", traceType: TraceTypes.Message);
                nameValueCollection = nameValueCollection.AddToDictionary(codeChallengeRequest);
            }

            securityHeaderLogic.AddFormActionAllowAll();

            logger.ScopeTrace(() => $"Up, Authentication request URL '{party.Client.AuthorizeUrl}'.");
            logger.ScopeTrace(() => "Up, Sending OIDC Authentication request.", triggerEvent: true);
            return(await nameValueCollection.ToRedirectResultAsync(party.Client.AuthorizeUrl));
        }