I have created a realm and added new keystore(RS384) in the Providers section
When I tried authenticate using postman. I am getting below error in Keycloak console
PublicKey wasn't found in the storage. Requested kid: 'Y3RDLAudovJPEU3Z9BMJL3OyuzqsgAj4424CpxnJqkI' . Available kids: '[]'
Kid is available in the Keys section for the Realm. I am not sure what is causing that. Any help on this is so much appreciated
Edit
Client Authentication
Added JWKS keys from certs endpoint
In Postman made call to token endpoint with client_assertion which has signed JWT and got response back "Invalid client: Unable to load Public key "
I think you gave wrong a value(or format) of "Private RSA Key" and "X509 Certificate" file when you add the key-store at Keycloak UI.
it is possible to get the public Key for RS384 by Postman and UI.
I demoed with Keycloak 18.0.0 with "ssh-keygen" & "openssl" on Ubuntu.
Generate RS384 private key and public key and certification file
ssh-keygen -t rsa -b 4096 -E SHA384 -m PEM -P "" -f RS384.key
openssl req -new -x509 -key RS384.key -out RS384-cert.pem -days 360
it will create three files
RS384-cert.pem <- certification file
RS384.key <- private key
RS384.key.pub <- public key
Add Keystore with 1.'s files
New Keystore will be created
Can get Key by Postman
can compare public key between UI and openssl generated it.
you can check API call value and JWT creator web site
with KID and public key
https://russelldavies.github.io/jwk-creator/
The issue is I did not add "use":"sig" in the JWKS that is kid is not available
Related
I received a new keystore .jks file for ssl connection to replace an old, but working, .jks keystore file, but I got "unexpected handshake message: serve_hello" error. I was told to make sure the keystore contains a client cert, so I used keytool to export its cert to a pem file, then use openssl to check the purpose. The result shows
Certificate purposes:
SSL client : No
SSL client CA : No
SSL server : Yes
SSL server CA : No
...
However when I applied the same process to check the old but working jks file I got the same result. Wonder if this is the right way to verify the certificate? And how to troubleshooting this handshake error with the new jks file?
Thanks!
The extended key usage extension contains OIDs which define the purpose:
id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
-- TLS WWW server authentication
-- Key usage bits that may be consistent: digitalSignature,
-- keyEncipherment or keyAgreement
id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
-- TLS WWW client authentication
-- Key usage bits that may be consistent: digitalSignature
-- and/or keyAgreement
https://datatracker.ietf.org/doc/html/rfc5280 Page 44
See: https://oidref.com/1.3.6.1.5.5.7.3.1 and https://oidref.com/1.3.6.1.5.5.7.3.2
When opening a certificate on Windows you can see the extension here:
I need to validate the signature of a JWT token which was signed on an ADFS server. I can validate a self-signed JWT token, but not a token received from ADFS. How should I be obtaining the public key?
To get the public key from the ADFS server I asked my colleague to export
the certificate from the ADFS server. On the ADFS console He looked in
"Services" > "Edit Federation Service Properties",
"General" tab where he found three entires. They were under the headings
"Token Signing", "Token Decrypting" and "Service Communication".
For each he viewed the certificate and then exported the DER certificate
(without private key). They were then transformed to PEM (using
openssl x509 -inform der -in cert.cer -out cert.pem) but none of these keys
allow my code to validate the sniffed JWT tokens.
My Java code takes a JWT Token and a Public Key, and validates that the token was signed with the Public Key. If I use a self-signed key pair and a self generated JWT Token then the code appears to work, and reports the signature is OK. When the token is copied from an HTTP Header in a message from ADFS the same code reports the signature is invalid.
Here is the code I use to load the PEM public key:
FileInputStream fis = new FileInputStream(publicKeyFile)
Reader keyReader = new InputStreamReader(publicKeyStream);
PemReader pemReader = new PemReader(keyReader);
PEMParser pemParser = new PEMParser(pemReader);
Object pemObject = pemParser.readObject();
if (pemObject instanceof X509CertificateHolder) {
X509CertificateHolder x509CertificateHolder = (X509CertificateHolder) pemObject;
X509Certificate x509Certificate = new JcaX509CertificateConverter()
.setProvider("BC").getCertificate(x509CertificateHolder);
return x509Certificate.getPublicKey();
}
Here is the code I use to validate the signature:
String signatureAlgorithm = publicKey.getAlgorithm();
Signature signatureInstance = Signature.getInstance(signatureAlgorithm);
signatureInstance.initVerify(publicKey);
byte[] messageBytes = Base64.encodeBase64(message.getBytes(UTF_8));
signatureInstance.update(messageBytes);
byte[] receivedSignature = Base64.decodeBase64URLSafe(signature);
return signatureInstance.verify(receivedSignature);
(I've removed the exception handling and resource closing for brevity above.
I'm using tomcat's Base64 class.)
The code runs without error but indicates that the signature is not valid. It seems to me that any of the below could be wrong:
None of the public keys extracted from the ADFS server are the relevant public key.
The conversion of the public keys from .cer to .pem may be incorrect.
The code to validate the signature, or load the public key, may be wrong.
Refer this and this.
The keys you refer to:
"Token Signing" - used for a SAML token derived from a CP or RP trust e.g. federation via SAML or WS-Fed
"Token Decrypting" - likewise
"Service Communication" - used for server SSL communication
For a JWT, I assume you are using OpenId Connect?
You use:
https://[Your ADFS hostname]/adfs/.well-known/openid-configuration
This has a pointer to the keys.
I am using nimbus-jose-jwt 5.14 and I generated RSA key pair with the following code
KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
gen.initialize(2048);
KeyPair keyPair = gen.generateKeyPair();
JWK jwk = new RSAKey.Builder((RSAPublicKey)keyPair.getPublic())
.privateKey((RSAPrivateKey)keyPair.getPrivate())
.keyUse(KeyUse.SIGNATURE)
.keyID(UUID.randomUUID().toString())
.build();
Now I need to expone some "metadata" about the public key:
e
kid
kty
n
use
x5c
How can I obtain x5c ? Is it possible to generate X509 certificate with this library? This field is null:
if (jwk.getX509CertChain() == null)
You have generated a key pair, not a certificate. A certificate contains a public key but it is not derived from it, so you can't get a certificate directly from the public key.
To verify a JWT the recipient only needs the public key, so publishing the x5c is in fact unnecesary for this purpose
If you really want to publish a certificate, I suggest to generate it with OpenSSL and import the public key in your code to get the JWK parameters
openssl req -x509 -newkey rsa:2048 -keyout key.pem -days 365 -out certificate.pem
I am using DelphiMongoDB from Grijjy (DelphiMongoDB) which is working pretty cool so far. But I can't find any functions to authenticate against a MongoDB. Did anybody getting this work or figured out how to do it?
Thanks and best regards
Update: The most up to date version of the Grijjy driver now supports TLS, X.509 client certificate authentication, SCRAM SHA-1 and SHA-256 authentication. We have also tested it against MongoDB Atlas instance at Azure.
Here is a simple example of how to use the authentication.
var
Settings: TgoMongoClientSettings;
Client: IgoMongoClient;
Database: IgoMongoDatabase;
Collection: IgoMongoCollection;
Doc: TgoBsonDocument;
begin
Settings := TgoMongoClientSettings.Create;
Settings.Secure := True;
Settings.AuthMechanism := TgoMongoAuthMechanism.SCRAM_SHA_1;
Settings.AuthDatabase := 'admin';
Settings.Username := 'username';
Settings.Password := 'password';
//Settings.QueryFlags := [TgoMongoQueryFlag.SlaveOk];
Client := TgoMongoClient.Create('my.mongodb.server.com', 27017, Settings);
Database := Client.GetDatabase('mydatabase');
Collection := Database.GetCollection('mycollection');
for Doc in Collection.Find() do
Writeln(Doc.ToJson(TgoJsonWriterSettings.Pretty));
end;
Legacy: Yes, the published Grijjy driver does not support authentication, but we have tested it internally and may add this ability in the near future to Github. You are also welcome to make a pull request if you want to adapt the following changes:
MongoDB currently supports 2 types of authentication, SCRAM and x.509 Certificate Authentication. Internally we have tested the x.509 Certificate Authentication, but the current driver on Github does not reflect this ability. We have not experimented with SCRAM yet.
To make it work with the MongoDB driver we published on Github, you may have to make a couple of changes.
You need to create a self-signed CA and certificate for your MongoDB server.
You need to configure your MongoDB server to use certs.
You need to create a self-signed certificate for your MongoDB client or clients. You can use the same cert for all clients.
You need to enable SSL/TLS connections and use your client certificate with the MongoDB driver.
1 To create all the certificates, you need an existing CA or create a self-signed CA. You can use the openssl.exe binary to do most of this:
Create root certificate authority (ca.pem and privkey.pem):
openssl req -out ca.pem -new -x509 -days 3650 -subj "/C=US/ST=California/O=Company/CN=root/emailAddress=root#domain.com"
To create a self-signed certificate for your MongoDB server (server.pem):
openssl genrsa -out server.key 2048
openssl req -key server.key -new -out server.req -subj "/C=US/ST=California/O=Company/CN=db.myserver.com/emailAddress=user#domain.com"
openssl x509 -req -in server.req -CA ca.pem -CAkey privkey.pem -CAcreateserial -out server.crt -days 3650
type server.key server.crt > server.pem
openssl verify -CAfile ca.pem server.pem
2 To configure MongoDB to use certs on the Windows version (similar on other versions), edit the c:\data\mongod.cfg:
systemLog:
destination: file
path: c:\data\log\mongod.log
storage:
dbPath: c:\data\db
net:
port: 27017
bindIp: 127.0.0.1
ssl:
mode: requireSSL
PEMKeyFile: c:\data\server.pem
CAFile: c:\data\ca.pem
{allowConnectionsWithoutCertificates: true }
{allowInvalidHostnames: true }
You may need allowInvalidHostnames to True if you are using a self signed certificate.
3 To create a self-signed certificate for your MongoDB client (client1.pem):
openssl genrsa -out client1.key 2048
openssl req -key client1.key -new -out client1.req -subj "/C=US/ST=California/O=Company/CN=client1/emailAddress=user#domain.com"
openssl x509 -req -in client1.req -CA ca.pem -CAkey privkey.pem -CAserial ca.srl -out client1.crt -days 3650
type client1.key client1.crt > client1.pem
openssl verify -CAfile ca.pem client1.pem
Note: You will also need to use the client certificate in whatever tool you are using to admin the MongoDB server.
4 To enable SSL/TLS connections for MongoDB driver you may have to change the source files. Our unit Grijjy.Http shows how to enable the driver for ‘https’. Essentially you need to do 2 things to the Connection inside the Grijjy.MongoDB.Protocol unit probably within the method TgoMongoProtocol.Connect :
Set Connection.SSL := True;
Set the Connection.Certificate to the client1.pem you created.
You will have to do some testing, but I hope it points you in the correct direction to make it work. Would love your contribution to the open source project if you can.
As far as I can understand the sources, https://github.com/grijjy/DelphiMongoDB/ doesn't support authentication.
Also from the source, https://github.com/stijnsanders/TMongoWire doesn't either.
FireDAC Mongo uses the C Mongo client library, which supports authentication.
Our Open Source SynMongoDB.pas supports authentication, FPC and almost all Delphi versions (even pre-Unicode). Using variant late-binding to access the BSON/JSON content, it is pretty easy to work with it. Just check the corresponding documentation pages. You can write for instance:
var doc: variant;
...
doc := Coll.FindOne(5);
writeln('Name: ',doc.Name);
writeln('Number: ',doc.Number);
or
var docs: TVariantDynArray;
...
Coll.FindDocs(docs);
for i := 0 to high(docs) do
writeln('Name: ',docs[i].Name,' Number: ',docs[i].Number);
The TMongoClient.OpenAuth method supports both old/deprecated MONGODB-CR method, and the new SCRAM-SHA-1 method:
Client := TMongoClient.Create('localhost',27017);
try
DB := Client.OpenAuth('mydb','mongouser','mongopwd');
...
Note that even if it is part of the mORMot framework, this unit is stand-alone: you don't need to use the ORM, SOA, or MVC parts of the framework - even if it works very well with the ORM, and is able to convert SQL-like statements into MongoDB pipelines, which is a unique very powerful feature. Another unique feature is proper Decimal128 support.
Over a network, also ensure that you use a TLS connection to the server. SynMongoDB.pas can do that under Windows, with no external OpenSSL library needed (it uses the raw Windows SO API).
I am currently testing with EJBCA while having a problem in accessing the administration page.
The EJBCA-4.0.13 is running on CentOS 6.2, with apache-ant-1.8.4, jboss-5.1.0-GA, mysql and mysql-connector-java. Installation is OK and no error occured in the jboss server log and I can access the EJBCA public web page with the url: https://:8443/ejbca. While I cannot access the administration page(https://:8443/ejbca/adminweb) with this information:
Authorization Denied
Cause: Your certificate is revoked or cannot be located in the database.
Any idea will be appreciated!
This is done in LocalCertificateStoreSessionBean.authenticate method. This could mean that you have not properly generated SuperAdmin certificate, or it is revoked, timed out or is issued by another CA that EJBACA's AdminCA.
Check your superadmin.p12 with:
openssl pkcs12 -nokeys -in ./superadmin.p12 -out superadmin.pem
openssl x509 -in ./superadmin.pem -text