Open Smallwood19 opened 5 years ago
I made a fork and added some code from BouncyCastle to perform the signature validation :(https://github.com/Smallwood19/Owin.Security.Keycloak)
I'm not able to reproduce this behavior. The Microsoft method ValidateSignature seem to work correctly for me when using the Keycloak .NET library in a WebApi application.
When testing this I didn't have a Web client that stores the access token in local storage (so no "access_token" in cookie etc). But instead I manipulated the JWT access token manually before sending it in the Authentication HTTP header (Bearer: xxxx) to the WebApi application, changing the realm_access/roles. The Keycloak library fails as expected in the ValidateSignature method when doing this, as the JWT payload no longer matches the JWT signature.
The access tokens generated by my Keycloak server uses RS256 encryption (which uses public/private key pair, where as HS256 would use a shared encryption secret). The JWT header for me looks something like this: { "alg": "RS256", "typ": "JWT", "kid": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
Which settings are your settings when initializing the Keycloak .NET library? app.UseKeycloakAuthentication(new KeycloakAuthenticationOptions { ... }
I am using the following packages and settings:
<package id="Microsoft.IdentityModel.Logging" version="1.1.4" targetFramework="net461" /> <package id="Microsoft.IdentityModel.Protocol.Extensions" version="1.0.4.403061554" targetFramework="net461" /> <package id="Microsoft.IdentityModel.Tokens" version="5.1.4" targetFramework="net461" />
<package id="System.IdentityModel.Tokens.Jwt" version="5.1.4" targetFramework="net461" />
Settings:
SignInAsAuthenticationType = persistentAuthType,
AuthenticationType = persistentAuthType,
DisableAllRefreshTokenValidation = true,
ForceBearerTokenAuth = true,
EnableBearerTokenAuth = true,
TokenClockSkew = TimeSpan.FromSeconds(2)
My Keycloak Server Version is: 4.8.2.Final
My encryption is also RS256.
I too was expecting the Microsoft ValidateSignature method to throw an error, but for some reason with this combination it let it through. My colleague and I both watched it in disbelief. I'm not sure what else could have let that happen. Your code works great.
Thanks.
On Thu, Apr 4, 2019 at 4:56 AM highbyte notifications@github.com wrote:
I'm not able to reproduce this behavior. The Microsoft method ValidateSignature seem to work correctly for me when using the Keycloak .NET library in a WebApi application.
When testing this I didn't have a Web client that stores the access token in local storage (so no "access_token" in cookie etc). But instead I manipulated the JWT access token manually before sending it in the Authentication HTTP header (Bearer: xxxx) to the WebApi application, changing the realm_access/roles. The Keycloak library fails as expected in the ValidateSignature method when doing this, as the JWT payload no longer matches the JWT signature.
The access tokens generated by my Keycloak server uses RS256 encryption (which uses public/private key pair, where as HS256 would use a shared encryption secret). The JWT header for me looks something like this: { "alg": "RS256", "typ": "JWT", "kid": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" }
Which settings are your settings when initializing the Keycloak .NET library? app.UseKeycloakAuthentication(new KeycloakAuthenticationOptions { ... }
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/mattmorg55/Owin.Security.Keycloak/issues/14#issuecomment-479832357, or mute the thread https://github.com/notifications/unsubscribe-auth/AqvFBpdF8I9I-_fXDa1gQA-SeTTKeZMXks5vdcxngaJpZM4caobg .
-- John Lewis Consulting 618-444-5131 johnlewisconsulting@gmail.com
I'm using the same Microsoft .NET library versions, and Keycloak server 4.8.3.
The only way I've been able to bypass signature validation is to set option KeycloakAuthenticationOptions.AllowUnsignedTokens=true (which you shouldn't do!), and skipping sending the JWT signature part of the Access Token to the API.
By looking at the Microsoft method JwtSecurityTokenHandler.ValidateSignature(string token, TokenValidationParameters validationParameters) https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/rel/5.1.5/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs it seem to do the correct thing. The additional call you invoke in your fork (to JwtSecurityTokenHandler.ValidateToken) will eventually call the same method (ValidateSignature). So it's a bit of a mystery to me.
Thanks, but I cannot take credit for the library as a whole, I've only made a few bug fixes and compatibility with newer Keycloak server versions.
I appreciate you taking a look at this. If we ever discover what allowed us to circumvent the exception handling, we'll let you know.
On Mon, Apr 8, 2019 at 4:28 AM highbyte notifications@github.com wrote:
I'm using the same Microsoft .NET library versions, and Keycloak server 4.8.3.
The only way I've been able to bypass signature validation is to set option KeycloakAuthenticationOptions.AllowUnsignedTokens=true (which you shouldn't do!), and skipping sending the JWT signature part of the Access Token to the API.
By looking at the Microsoft method JwtSecurityTokenHandler.ValidateSignature(string token, TokenValidationParameters validationParameters)
https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/rel/5.1.5/src/System.IdentityModel.Tokens.Jwt/JwtSecurityTokenHandler.cs it seem to do the correct thing. The additional call you invoke in your fork (to JwtSecurityTokenHandler.ValidateToken) will eventually call the same method (ValidateSignature). So it's a bit of a mystery to me.
Thanks, but I cannot take credit for the library as a whole, I've only made a few bug fixes and compatibility with newer Keycloak server versions.
— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/mattmorg55/Owin.Security.Keycloak/issues/14#issuecomment-480756215, or mute the thread https://github.com/notifications/unsubscribe-auth/AqvFBmfL9W4ssrB-uNdKbWg7kpRRgX2Rks5vewu0gaJpZM4caobg .
-- John Lewis Consulting 618-444-5131 johnlewisconsulting@gmail.com
It is possible to manipulate the JWT being sent to this library. The existing calls to the Microsoft ValidateSignature method (jwt = ValidateSignature(securityToken, validationParameters);) fail to compare the token against the signature.
Assuming Chrome is your browser and you have some sort of web front-end, you can follow these steps to reproduce the security hole:
These steps only work if your front-end also fails to validate the token signature before sending to the API.