Example #1
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]);
                }
            }
        }
        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));
        }