verify a jwt token with lua/openresty - lua

i've a jwt token from an aws cognito login process. this token needs to be sent from the application to some other apis (via cookie or bearer header, i've not yet decided).
the receiving apis has been proxied behind nginx/openresty, so i'm thinking to validate the jwt token before the upstream
i'm using this library (the seems the most updated)
https://github.com/cdbattags/lua-resty-jwt
then i followed these steps:
download the jwks file from my account
wget https://cognito-idp.eu-west-1.amazonaws.com/eu-west-1_5zCVSiMVH/.well-known/jwks.json
convert the jwks to pem with jwks2pem
cat jwks.json| jwks2pem > key.pem
then this code
local jwt = require "resty.jwt"
local key = [[ -----BEGIN PUBLIC KEY-----
(content of key.pem)
-----END PUBLIC KEY-----
]]
local jwt_token = ""
local jwt_obj = jwt:load_jwt(jwt_token)
local verified = jwt:verify_jwt_obj(key, jwt_obj)
ngx.say(cjson.encode(jwt_obj))```
the code fails:
$ resty jwt.lua
{"valid":false,"reason":"invalid algorithm: RS256","verified":false}
where i'm wrong?

ok, the problem is the key.
i've successfully obtained the pem key from jwks with this other tool https://www.npmjs.com/package/jwk-to-pem
the validation now works

Related

How to get page using client and server certificate

How to retrieve page over https using client and server certificate in .NET 6 C# ?
Using curl this works:
curl --key private.key --cert server.crt https://example.com
How to convert this to C# ?
private.key file is text file in format
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxTvKy3WRPqli9ODpIcTb8Bhnxa2x+8xip/kWq...
server.crt is text file in format
-----BEGIN CERTIFICATE-----
MIIEnzCCAoegAwIBAgIIIJKu2MhhxF0wDQYJKoZIhvcNAQENBQAwLjEeMBwGA1UE
I tried curl to c# https://github.com/olsh/curl-to-csharp online version https://curl.olsh.me/ to convert
It throws errors
Certificate type "Pem" is not supported
Parameter "--key" is not supported
and generates code
var handler = new HttpClientHandler();
using (var httpClient = new HttpClient(handler))
using (var request = new HttpRequestMessage(new HttpMethod("GET"), "https://example.com/"))
var response = await httpClient.SendAsync(request);
Server requires private key from file private.key for authentication.
How to pass private key to server ?
This is ASP.NET 6 MVC application running in Debian.

Azure Key Vault - Certificate generation

I am using the following script to generate a new ROOT CA that will be used to generate sub-ca's and client certificates.
New-SelfSignedCertificate -CertStoreLocation "cert:\CurrentUser\My" -Subject "CN=$certificateCleanName" -KeySpec Signature -KeyUsage CertSign -TextExtension #("2.5.29.19 ={critical} {text}ca=1")
This works perfectly, but I would prefer to generate them in the Key Vault Directly (via Powershell).
I know you can generate a self signed certificate in the key vault directly with this command:
$manualPolicy = New-AzureKeyVaultCertificatePolicy -SubjectName "CN=something.com" -ValidityInMonths 24 -IssuerName Self -RenewAtNumberOfDaysBeforeExpiry 100
$certificate = Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $manualPolicy
However, with the command above, I am not able to generate the exact same certificate properties as in the first command that use to generate the certificate locally.
Any idea how I can specify the following arguments to create the certificate with the exact same settings directly in the KeyVault?
-KeyUsage CertSign -TextExtension #("2.5.29.19 ={critical} {text}ca=1")

APNS Provider API and Postman

I'm trying to use Postman to create and test Apple Notifications in my iOS app.
For a reason I don't get, requests I send from Postman to either https://api.development.push.apple.com/3/device/<token-device> or https://api.push.apple.com/3/device/<token-device> fail without getting any HTTP response.
What I've done so far:
1 - created and exported a APNS certificate from my developer.apple.com account (as explained there).
2 - converted this .p12 certificate with a recent version of openssl (1.0.2l) to a .pem cert and key like this:
openssl pkcs12 -in apns.p12 -out apns.crt.pem -clcerts -nokeys
openssl pkcs12 -in apns.p12 -out apns.key.pem -nocerts -nodes
3 - configured Postman (Preferences > certificates) to use these .pem files for both Provider API urls (dev and prod)
4 - setup a POST request to those Provider API endpoint for my device token with a apns-topic header that has my bundle id for value, and a HTTP body like this:
{
"aps" : {
"alert" : {
"title" : "Game Request",
"body" : "Bob wants to play poker"
}
}
}
It fails with "Could not get any response, blablabla".
If I check what happens it the Postman console, I see:
POST
https://api.development.push.apple.com/3/device/12340e529f85a145b567736e7fd84c9d7e42a43a3c343ec378c2ff071011e4
06:18:08.236
Error: Parse Error
Client Certificate:
keyPath:"/Users/thomas/wksp_myproj/apns.key.pem"
pemPath:"/Users/thomas/wksp_myproj/apns.crt.pem"
Request Headers:
cache-control:"no-cache"
Postman-Token:"99615df2-b2aa-4a51-8d15-8ce27f4e8ca9"
Content-Type:"application/json"
apns-topic:"myproj.app"
Also, when I test with openssl as explained there:
openssl s_client -connect api.development.push.apple.com:443 -cert apns.pem -debug -showcerts -CAfile GeoTrust_Global_CA.pem
I get a lot of outputs with at the end:
HTTP/2 client preface string missing or corrupt. Hex dump for received bytes: 0aread from 0x7f9445c215c0 [0x7f9446015c03] (5 bytes => 0 (0x0))
read:errno=0
What's going wrong?
OK, forget about Postman, I've ended up using curl with http2 and an updated version of openssl (1.0.2l) and it's working just fine. For those who would like to see an curl command example, it's here.

Ruby - Connect with SSL and authenticate via client certificate - sslv3 alert bad certificate

I'm trying to connect a webcrawler that accesses a certain site via SSL and queries my data on that site. The authentication of this site is via a self-signed Digital Certificate. At the moment I want to access the site, I upload this certificate in .pfx format to my api, convert it to .pem, and when I try to access the site with this certificate, the response comes with status 403 (forbidden ).
However, when I try to access the site through a browser with the certificate in .pfx format I usually get it.
I already tried using Mechanize, and it worked for a while (until a few months ago it worked), but then it started to give the error:
SSL_connect returned = 1 errno = 0 state = SSLv3 read finished A: sslv3 alert bad certificate
The site is old, it does not receive updates frequently.
After that I already tried to use the net / http lib and the error persisted, I tried to use the httprb gem and lastly I tried with Faraday. All attempts ended either in that error quoted above or with the response status == 403.
What can I do to be able to connect? Is there something wrong with my script? Is it missing any information I need to get through?
Code:
# Faraday customs method:
class FaradayHttp
def with_openssl
system "openssl pkcs12 -in my-certificate-path -out certificate-output-path -nodes -password pass:certificate-password"
def cert_object
OpenSSL::X509::Certificate.new File.read("certificate-output-path")
end
# create PKey
def key_object
OpenSSL::PKey.read File.read("certificate-output-path")
end
faraday = Faraday::Connection.new 'https://example-site.com',
:ssl => {
certificate: cert_object,
private_key: key_object,
version: :SSLv3,
verify: false
}
faraday
end
end
# Controller that try to connect with the ssl server:
agent = FaradayHttp.new.with_openssl
page = agent.get '/login_path'
# mypki will prompt you for certificates
require 'mypki'
# faraday will use certificates from mypki
require 'faraday'
faraday = Faraday::Connection.new 'https://example-site.com'
faraday.get '/login_path'

How can I use a PEM certificate with password?

I'm having plenty of trouble trying to use a certificate that has a password on ruby. I'm using rest-client, but that's not a requirement.
This is the cURL-equivalent of the call I need to make:
curl -E certificate.pem:PASSWORD -d ident=language -d data="test" "https://theurl"
I tried many things, but I can't get the password part working. Here's what I have so far:
cert = OpenSSL::X509::Certificate.new(File.read("#{RAILS_ROOT}/certificate.pem"))
reply = RestClient.post("https://theurl", {:ident => 'language', :data => 'test'}, {:ssl_client_cert => cert})
I've tried putting the password everywhere, as :password and :ssl_client_key, I've looked through all documentation I could find but there's nowhere that will accept this password.
This is the error I always get:
SSL_connect returned=1 errno=0 state=SSLv3 read finished A: sslv3 alert handshake failure
What am I missing?
The way you uses curl with option -E, you are specifying a private key with a certificate.
(from the cURL man page)
-E/--cert
(SSL) Tells curl to use the specified
client certificate file when getting a
file with HTTPS, FTPS or another
SSL-based protocol. The certificate
must be in PEM format. If the optional
password isn't specified, it will be
queried for on the terminal. Note that
this option assumes a "certificate"
file that is the private key and the
private certificate concatenated! See
--cert and --key to specify them independently.
So in order to do the samething with RestClient, you can try using the ssl_client_key option. Like:
:ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),

Resources