コード例 #1
0
        protected virtual string BuildChallengeUrl(AuthenticationProperties properties, string redirectUrl)
        {
            var bytes = new byte[16];

            RandomNumberGenerator.Fill(bytes);
            var nonce = Base64UrlTextEncoder.Encode(bytes);

            properties.Items.Add("nonce", nonce);

            string payload = Convert.ToBase64String(Encoding.UTF8.GetBytes($"nonce={nonce}&return_sso_url={redirectUrl}?returnUrl={properties.RedirectUri}"));

            using var sha256mac = new HMACSHA256(Encoding.UTF8.GetBytes(Options.AuthenticationSecret));
            var challengeBytes = sha256mac.ComputeHash(Encoding.UTF8.GetBytes(payload));
            var codeChallenge  = BitConverter.ToString(challengeBytes).Replace("-", "").ToLower();

            var parameters = new Dictionary <string, string>
            {
                { "sso", Uri.EscapeUriString(payload) },
                { "sig", codeChallenge },
            };

            Response.Cookies.Append("StateCookie", Options.StateDataFormat.Protect(properties));

            return(QueryHelpers.AddQueryString(Options.AuthorizationEndpoint, parameters));
        }
コード例 #2
0
        public void DecodeToBase64String_ReturnsValid_Base64String(string text, string expectedValue)
        {
            // Arrange & Act
            var actual = Base64UrlTextEncoder.DecodeToBase64String(text);

            // Assert
            Assert.Equal(expectedValue, actual);
        }
コード例 #3
0
        public void EncodeInternal_Replaces_UrlEncodableCharacters(string base64EncodedValue, string expectedValue)
        {
            // Arrange & Act
            var result = Base64UrlTextEncoder.EncodeInternal(base64EncodedValue);

            // Assert
            Assert.Equal(expectedValue, result);
        }
コード例 #4
0
        public void DataOfVariousLengthRoundTripCorrectly()
        {
            for (int length = 0; length != 256; ++length)
            {
                var data = new byte[length];
                for (int index = 0; index != length; ++index)
                {
                    data[index] = (byte)(5 + length + (index * 23));
                }
                string text   = Base64UrlTextEncoder.Encode(data);
                byte[] result = Base64UrlTextEncoder.Decode(text);

                for (int index = 0; index != length; ++index)
                {
                    Assert.Equal(data[index], result[index]);
                }
            }
        }
コード例 #5
0
        protected override async Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            var query = Request.Query;

            byte[] challengeBytes;
            using var sha256mac = new HMACSHA256(Encoding.UTF8.GetBytes(Options.AuthenticationSecret));
            challengeBytes      = sha256mac.ComputeHash(Encoding.UTF8.GetBytes(query["sso"]));

            byte[] signatureBytes = HexStringToByteArray(query["sig"]);

            if (signatureBytes.Length != challengeBytes.Length)
            {
                return(HandleRequestResult.Fail("Signature mismatch"));
            }

            for (int ix = 0; ix < signatureBytes.Length; ++ix)
            {
                if (signatureBytes[ix] != challengeBytes[ix])
                {
                    return(HandleRequestResult.Fail("Signature mismatch"));
                }
            }

            var properties = Options.StateDataFormat.Unprotect(Request.Cookies["StateCookie"]);

            if (properties == null)
            {
                Logger.LogError("Authentication Properties not found");

                properties = new AuthenticationProperties();
            }
            else if (!ValidateCorrelationId(properties))
            {
                //return HandleRequestResult.Fail("Discourse correlation failed.", properties);
                Logger.LogError("Discourse correlation failed.");
            }

            string encodedData = Encoding.UTF8.GetString(Base64UrlTextEncoder.Decode(query["sso"]));

            var userInfo = HttpUtility.ParseQueryString(encodedData);

            var identity = new ClaimsIdentity(ClaimsIssuer);

            foreach (var key in userInfo.AllKeys)
            {
                switch (key)
                {
                case "groups":
                {
                    var groups = userInfo[key].Split(",");
                    foreach (var group in groups)
                    {
                        identity.AddClaim(new Claim(ClaimTypes.Role, group));
                    }
                    break;
                }

                case "name":
                {
                    identity.AddClaim(new Claim(ClaimTypes.Name, Uri.UnescapeDataString(userInfo[key]).Replace('+', ' ')));
                    break;
                }

                case "email":
                {
                    identity.AddClaim(new Claim(ClaimTypes.Email, userInfo[key].ToLowerInvariant()));
                    break;
                }

                case "external_id":
                {
                    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userInfo[key]));
                    break;
                }

                case "username":
                {
                    identity.AddClaim(new Claim(ClaimTypes.UserData, userInfo[key]));
                    break;
                }

                case "return_sso_url":
                case "nonce":
                    break;

                default:
                    identity.AddClaim(new Claim(key, userInfo[key]));
                    break;
                }
            }

            if (string.IsNullOrEmpty(query["returnUrl"]) == false)
            {
                properties.RedirectUri = query["returnUrl"];
            }

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

            return(HandleRequestResult.Success(ticket));
        }