I have implemented an OpenID 1.1 provider in Java but I am having trouble with smart clients using an assoc_handle from associate coming up with different signatures. Dumb clients relying on check_authentication work fine. Specifically, I am testing against LiveJournal and it keeps returning:
signature_mismatch: Prior association invalidated ID provider response.
The body of my HMAC() function is:
public static byte[] HMAC(byte[] secret, String token_contents) {
SecretKey sk = new SecretKeySpec(secret, "HMACSHA1");
Mac m = Mac.getInstance(sk.getAlgorithm());
m.init(sk);
return m.doFinal(token_contents.getBytes("UTF-8"));
}
The token_contents for calling HMAC() comes from the following code during the handling for checkid_setup. That is, the signing is being done on mode,identity,return_to and this is also the value of the signed response parameter.
String token_contents = String.format(
"mode:id_res\nidentity:%s\nreturn_to:%s\n",
identity, return_to);
And finally, the secret is the base64-decoded version of mac_key returned by the initial associate call (e.g. retrieved via secret(assoc_handle) as per the spec). I've done a fair amount of testing to make sure the enc_mac_key can be decrypted properly.
Any thoughts? Is there anything glaringly wrong with this?
Or ... is there a simple, stand-alone client that anyone knows of which would do OpenID 1.1 and trace out its steps. Given that I may be able to figure out where I'm calculating things differently.
The problem in my case was using base64url encoding on output of key values (mac_key, enc_mac_key, dh_server_public) instead of standard base64. In Apache Commons I was using encodeBase64URLSafeString instead of simply encodeBase64String. This was an unfortunate carry over from having worked in Open ID Connect previously and I misunderstood the nature of the function.
Anyway, something that helped me discover the answer was using the simply excellent OpenID4Java and its simple-openid JSP sample. Immediately it barfed out errors on my signature, complaining that it was 168 bits (instead of 160).
Related
There is an OCSP Responder to which the server will communicate and staple the response. How can the client check for the stapled response in C# or Java. Bouncy Castle, Chiklat, native lib - they call seem to have ways for the client to talk to the OCSP responder but not read the stapled response.
As you already mentioned correctly, stapling is done during the handshake. I only know how to do this in the C# port of Bouncy Castle, since I'm implementing a PKIX crypto component based on BC, which also considers OCSP and which simplifies the BC calls dramatically (I will report it here when I'm ready to publish an alpha version, will most likely be open source).
First of all, according to RFC6066, stapling responses are only sent if you ask for them in the Client-Hello. To enable this, you have to override GetClientExtensions of your TlsClient (e.g. when you inherit from DefaultTlsClient):
using BouncyTls = Org.BouncyCastle.Crypto.Tls;
...
public override IDictionary GetClientExtensions() // Override in your TlsClient class
{
IDictionary clientExtensions = base.GetClientExtensions();
clientExtensions = BouncyTls.TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions);
byte type = BouncyTls.CertificateStatusType.ocsp;
var request = new BouncyTls.OcspStatusRequest(null, null);
BouncyTls.TlsExtensionsUtilities.AddStatusRequestExtension(clientExtensions, new BouncyTls.CertificateStatusRequest(type, request));
return clientExtensions;
}
After that, the server will send the stapling response if supported.
However, the response is only available during the handshake, if you see Bouncy Castle's source code, it is cleared on CompleteHandshake in your TlsClientProtocol instance.
Therefore you have to intercept here too:
protected override void CompleteHandshake() // Override in your TlsClientProtocol class
{
// After the handshake completed, we do not have any access to the handshake data anymore
// (see TlsClientProtocol.CleanupHandshake). Therefore we must intercept here to gather information
YourValidationOfTheOcspResponse(mCertificateStatus);
// mCertificateStatus holds the response. It is cleared after the following call:
base.CompleteHandshake();
}
I spent hours until I understood what bouncy castle is doing here and how the stapling response can be extracted, although the code to do so is very simply.
A good starting point is always to find the corresponding RFC and compare fields with BC, since Bouncy Castle uses the exact same identifiers in most cases.
Just another side note; to comply with the TLS standard, use RaiseAlertFatal to write the correct error records (see RFC8446) if a status entry tells that a certificate is revoked, etc.
Team,
I have an requirement like i have to support to my partner (third party) portal to call us directly by making api call with credentials from their browser.
e.g.) Partner portal browser makes AJAX Call with below:
URL ---> https://example.com/request
HEADER ---> user_id : foo
HEADER ---> password : mypasswd
payload ---> {
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
And their browser/portal is accessible/used by untrusted users of theirs. So now problem is since the call is from the front end; end user easily can inspect the browser to see the network api calls along with credential we have given to our partner to authorise at our side.
So i am planning to give suggestion to partner by asking them to encrypt the payload and headers in their portal backend server and render the encrypted information in the portal like below.
Encrypt (payload) using mypasswd.
Encrypt (password) using request_time <NOW OPTIONAL TO PASS>
So now,
e.g.) URL ---> https://example.com/request
HEADER ---> user_name : foo
HEADER ---> password : ENCRYPTED<mypasswd> <-- OPTIONAL
payload ---> ENCRYPTED<
{
"request_time" : 2232876435,
"request_name" : "get_user_info",
...
...
}
>
So in our system we will decrypt payload with mypasswd retrieved for user_id foo. so if decryption is successful, then the request is from valid resource.
Now the end portal user cannot understand the request from browser inspection.
NOTES:
I can't suggest my partner to call from their backend.
From the request payload i can identify repeated same request through unique transaction id, so they can't resubmit the same request. Hence avoiding replay attack.
Questions:
Q1) Any flaw or suggestion on this solution?
Q2) Is it possible to identify the decryption using passphrase is success or not in java? I am new to encryption, so could you please share any code or link to achieve this?
yours thoughts much valuable to me.
TLDR:
References:
Basic encryption details
https://blog.storagecraft.com/5-common-encryption-algorithms/
https://www.veracode.com/blog/research/encryption-and-decryption-java-cryptography
https://gooroo.io/GoorooTHINK/Article/13023/The-difference-between-encryption-hashing-and-salting/2085#.W2L_KdgzZD0
Java Encryption
How to encrypt and decrypt String with my passphrase in Java (Pc not mobile platform)?
Java Security: Illegal key size or default parameters?
Identifying decryption is successful through this exception:
Given final block not properly padded
EDIT: I misunderstood the question. If the information is encrypted by the third party before it reaches the end-user then this approach is generally safe. Replay attacks are the main thing to look out for. If the request being made is idempotent then you don't really need to worry, but otherwise you might need to implement a short-lived database for used tokens along with an expiry time or something similar.
You are solving this problem the wrong way. Having the end user make this request to you on behalf of the third party is silly - if the request comes from their browser then by definition they control the information they are sending and the way it is sent. Encryption does nothing to solve this since the encryption logic is also client side.
The solution to this problem is to eliminate the end-user. The request should come directly from the third party to you. This might be from the end-user making a request to the third party API or it might not - it doesn't matter.
I have Java client running on Windows machine that calls remote EJB
on JBoss EAP/Wildfly running on Linux machine.
I use Kerberos to achieve SSO. Java client verifies the user against Windows domain
and pass his identity within EJB call to the JBoss server.
I started with JAAS and the builtin com.sun.security.auth.module.Krb5LoginModule.
It works correctly except one thing: user has to type his username and password
again. So, it is not a real SSO.
The problem is that Windows prohibits to export kerberos session key from its LSA credential cache.
It can be fixed by setting a specific Windows registry key on each client machine - but this is not acceptable for the customer.
Therefore I am trying to find an alternative solution.
I learned that Windows provides SSPI that shall be interoperable with GSSAPI used by Java. I use Waffle library to access SSPI from Java on the client. On the server I keep using JAAS, because it runs on Linux so I cannot use Waffle there.
I also learned that I don't need to implement LoginModule, rather I need SASL client.
So, I had a look how com.sun.security.sasl.gsskerb.GssKrb5Client works and I am trying to reimplement it using Waffle.
First step seems to work correctly - I obtain SSPI security context from Waffle,
then get the initial token and send it to the server.
The server accepts the token and respond with its own token.
And now the problem comes. In the original SASL client the 'unwrap' operation is
used to extract data from the server token, and 'wrap' operation is used to create
reply token to be sent to server.
GSSAPI wrap / unwrap operations shall correspond to SSPI EncryptMessage / DecryptMessage
operations according to Microsoft doc. This two methods are not available in Waflle, but are available
in NetAccountClient library.
However, I am not able to use them correctly. If I use a single SECBUFFER_STREAM then the DecryptMessage
is succesfull, however the data part of the token is not extracted and I don't know how to determine
the offset where it begins.
If I use SECBUFFER_STREAM and SECBUFFER_DATA as suggested by Microsoft docs, then I get an error:
com.sun.jna.platform.win32.Win32Exception: The message or signature supplied for verification has been altered
I also tried other combinations of SECBUFFER types as suggested elsewhere, but without success.
Any idea what am I doing wrong ?
To source code of unwrap method:
public byte[] unwrap(byte[] wrapper) throws LoginException {
Sspi.SecBuffer.ByReference inBuffer = new Sspi.SecBuffer.ByReference(Secur32Ext.SECBUFFER_STREAM, wrapper);
Sspi.SecBuffer.ByReference buffer = new Sspi.SecBuffer.ByReference();
buffer.BufferType = Sspi.SECBUFFER_DATA;
Secur32Ext.SecBufferDesc2 buffers = new Secur32Ext.SecBufferDesc2(inBuffer, buffer);
NativeLongByReference pfQOP = new NativeLongByReference();
int responseCode = Secur32Ext.INSTANCE.DecryptMessage(secCtx.getHandle(), buffers, new NativeLong(1), pfQOP);
if (responseCode != W32Errors.SEC_E_OK) {
throw handleError(responseCode);
}
byte[] data = buffer.getBytes();
return data;
}
I recently got to know about Json Web Token (JWT). Since I liked how it works I have started to implement it on my project. My project involves two apps to communicate. One is an android app and the other is Laravel web application.
The mobile app logs in after the user credential is authenticated from the server side.
I have sent the username and password to server from the mobile app and I have got the JWT in string format. But from this point onward I couldn't find a way to collect the JWT content.
I have gone through almost all possible shown (googled results) but I couldn't manage to get the contents, signature and header.
One of the method I have got a little bit further with, was using the following code, notice I have removed the setSigningKey():
try {
Claims claims = Jwts.parser().parseClaimsJwt(jwtHeaderAndClaim).getBody();
System.out.println("ID of the claims: " + claims.getId().toString());
}catch (Exception e){
Log.e("Exception: ", e.toString());
}
The above code generates the following error:
Exception: io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before 2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´
the jwtHeaderAndClaim is the JWT String after removing the signature part only (i.e: "xxxxxx.yyyyyyyy."). if i put the jwtString (xxxxxxx.yyyyyyyy.ccccccc) instead of jwtHeaderAndClaim the following error will occur:
Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are not supported
If I put the setSigningKey as shown in stormpath example:
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret())).parseClaimsJwt(jwtString).getBody();.
The above code will not work for two reasons:
1. I don't have the library
import javax.xml.bind.DatatypeConverter;
2. I don't know how to get the key.
But know that I don't need the key since this time I am trying to login and collect the user information's (like firstname, lastname, phone, etc), and the signature (token) so that the next time I send data to be stored to the server side I have the token to get access to the backend.
Can anyone please help me?
You have many questions. I try to answer some of them
io.jsonwebtoken.PrematureJwtException: JWT must not be accepted before
2016-06-14T10:20:09+0300. Current time: 2016-06-14T10:19:37+0300´
You are using nbf (not before) attribute in JWT. Do not use it (it is optional) or sets a range of validity given that the clocks of the devices will not be synchronized
From RFC 7519
The "nbf" (not before) claim identifies the time before which the JWT
MUST NOT be accepted for processing. The processing of the "nbf" claim requires that the current date/time MUST be after or equal to the not-before date/time listed in the "nbf" claim. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value MUST be a number containing a NumericDate value. Use of this claim is OPTIONAL.
Signed JWS
Exception: io.jsonwebtoken.UnsupportedJwtException: Signed JWSs are
not supported
Do you want to validate the signing key at client side or at server side?
If you use the JWT for authentication replacing user & password, and you are sending token in each request, you can validate the signature at server side.
If you want to validate the key on the app, do not use a symmetric key, because it could be a big vulnerability if it fell into the wrong hands. See. You can use and asymmetric key pair. Sign the JWT in server with the private key and validate on device with public key.
I don't have the library import javax.xml.bind.DatatypeConverter
String base64 = Base64.encodeToString(data, Base64.DEFAULT);
byte[] data = Base64.decode(base64, Base64.DEFAULT);
I don't know how to get the key.
Your key probably was generated on server side in this way
Key key = MacProvider.generateKey(SignatureAlgorithm.HS256);
byte data[] = key.getEncoded();
Make available the key data[] to client in the way you prefer. Using assymetric keys, you only need to make available the public key.
KeyPair keyPair = RsaProvider.generateKeyPair();
byte data[] = keyPair.getPublic().getEncoded();
How specifically is the state parameter related to the _csrf token in Spring OAuth2? Is state an encrypted version of _csrf as we would expect it to be?
Also, what specific Java syntax should be used to encode and encrypt a new _csrf value before encapsulating it into a new state parameter in Spring OAuth2?
THE CONTEXT
A client app redirects the user's web browser from the client app to the authorization server's authserver/login page. Then, in the authorization server app, a custom implementation of OncePerRequestFilter is used to redirect a request to /oauth/authorize?(list of params) into additional authentication steps, which ultimately redirect back into a new request to /oauth/authorize?(list of params). The problem is that the _csrf token changes during the additional authentication steps, and the documentation indicates that _csrf is used as the state parameter. This implies that the state value probably needs to be updated by the authorization server to reflect the new _csrf value.
HOW state IS GENERATED
The problem is that the encoded and encrypted value for state has already been set by the client app before the client app uses an OAuth2ClientAuthenticationProcessingFilter to transfer information for the authentication server to use while authenticating the user via the authentication steps mentioned above.
Some research indicates that the state key is generated by the client using a DefaultStateKeyGenerator, which in turn uses a RandomValueStringGenrator to generate a 6 character state value.
For example, in the original request made to /oauth/authorize?(list of params), the raw _csrf value is encoded into fupS1L, as shown in the following url:
/oauth/authorize?client_id=acme&redirect_uri=http://localhost:8080/login&response_type=code&state=fupS1L
If the _csrf value changes to a69fd23a-a393-4b27-a685-a323fd31db9a during the redirect flow, the value of fupS1L in the state parameter will no longer be valid, and the resulting token will not be authorized to permit access to protected resources.
What specific syntax do I use in order to convert the new _csrf value into an encrypted value similar to fupS1L that can be passed into a functional state parameter?
Also, is there any relationship between the state variable and the _csrf token? The RandomValueStringGenerator used by DefaultStateKeyGenerator seems to simply create a random 6 character String. I would like an authoritative answer by someone who has worked deeply with the code or even written it. I am doing a deep review of the code, so a casual passer by who reads the RandomValueStringGenerator source code and says state is not related to the csrf token would not be adding any value. The author of the API, however, would help us all out a lot by telling us how this works.
NOTE TO SPRING
It should not require this much digging to find documentation of such a simple thing.
I know it's quite old since its been asked. Still sharing what I know now, as I have worked through a similar requirement to pass a deeplink in the 'state' parameter. I wanted to redirect to this deeplink when flow comes back from the auth-server after a successful oauth sign-in session.
Primarily I followed this SOF answer -> https://stackoverflow.com/a/52462787/5107365. This suggests to extend the DefaultStateKeyGenerator to use the deeplink parameter from the request to AAS to encrypt+encode to set into the 'state' parameter. And, then the custom implementation of OAuth2ClientAuthenticationProcessingFilter.AuthenticationSuccessHandler is used to override determineTargetUrl method to decode+decrypt the state parameter when the flow comes back after successful auth. Hopefully it will help somebody who is in need of a similar requirement.