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)); }
public void DecodeToBase64String_ReturnsValid_Base64String(string text, string expectedValue) { // Arrange & Act var actual = Base64UrlTextEncoder.DecodeToBase64String(text); // Assert Assert.Equal(expectedValue, actual); }
public void EncodeInternal_Replaces_UrlEncodableCharacters(string base64EncodedValue, string expectedValue) { // Arrange & Act var result = Base64UrlTextEncoder.EncodeInternal(base64EncodedValue); // Assert Assert.Equal(expectedValue, result); }
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)); }