I'm developing a new REST Service using Quarkus (1.3.2.Final) and I'm trying to integrate Firebase Authentication with Smallrye-Jwt but it failed.
My first try was to point publickey.location to Google's URL and it failed because there are two keys and the correct publicKey to check signature depends on jwt "kid" header value:
mp.jwt.verify.publickey.location=https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com
mp.jwt.verify.issuer=https://securetoken.google.com/<projectId>
quarkus.smallrye-jwt.auth-mechanism=MP-JWT
quarkus.smallrye-jwt.enabled=true
My second try was create a service (Kind of "PublicKeyResolver") to request google's url and extract the correct public key based on "kid" claim value:
mp.jwt.verify.publickey.location=http://localhost:8080/api/certs/publicKey
That strategy failed because "Authorization" http header is not included in request for publicKey.
There is a way to integrate Quarkus and Firebase Authentication?
There is a way for Quarkus-Firebase integration. According to Quarkus documentation mp.jwt.verify.publickey.location is a location of Public Key. Moreover, supported public keys formats are defined as well (https://quarkus.io/guides/security-jwt#supported-public-key-formats):
Public Keys may be formatted in any of the following formats, specified in order of precedence:
Public Key Cryptography Standards #8 (PKCS#8) PEM
JSON Web Key (JWK)
JSON Web Key Set (JWKS)
JSON Web Key (JWK) Base64 URL encoded
JSON Web Key Set (JWKS) Base64 URL encoded
So you shall be aiming at specifying URL that contains Public Keys formatted as JWKS (as there is no way for Smallrye-Jwt to accept set of PKCS#8 PEMs). The "Google URL" you are trying to use, is not rfc7517 compliant JWK Set.
In order to make it work, you shall use this Google JWKS URL that is compliant with rfc7517:
mp.jwt.verify.publickey.location=https://www.googleapis.com/service_accounts/v1/jwk/securetoken#system.gserviceaccount.com
Related
My locally hosted bot that's integrated with Google Hangouts API uses python's Tornado module to accept user input from Google and responds with an appropriate reply. This is the request handler on the bot server:
class incomingRequestHandler(tornado.web.RequestHandler):
def post(self):
recievedData = json.loads(self.request.body.decode('utf-8'))
responseData = generateResponse(recievedData)
self.write({ 'text' : responseData })
This works great. Now I want to authenticate the incoming requests to make sure they're only coming from Google Hangouts.
The request from Google does have an Authorization bearer token in it's header and I'm sure that's what needs to be used for verification. As such, based on this article I took the recommended measures like using id_token.verify_oauth2_token() or querying https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 but neither solution seems to work.
Could someone point me in the right direction for this? Am I using the correct token even or is this the wrong method for verifying incoming requests?
This issue originated from me having no idea what a JWT was nor knowing that what I'd encountered was a JWT. Another symptom of trying to handle things yourself, I guess.
Anyway, the solution is simply to get the Google certificates from this link, use openssl to generate corresponding public keys and feed the key specified (by kid value) in the authentication token to the jwt.decode() method of python's jwt module.
Here's a snippet of the solution:
selectedKey = certs.get(jwtHeader.get('kid')) //certs is a dict containing the public keys from Google
checksum = jwt.decode(token, selectedKey, algorithms=["<value-of-alg>"], audience="<value-of-aud>", issuer="<value-of-iss>") //token is simply the authentication token as a string
Note the following bash command to be sued to convert Google's x509 certificates into pem format public keys:
openssl x509 -pubkey -noout -in key.pem
I don't think python has a very modular solution for the above yet. Do let me know if there is.
I have been trying to use Httpclient to access an API. It requires me to submit a key to authenticate but cant seem to get the right combination to go through. So my question is how do I specifically pass the authentication key and path in my headers?
I'm using the site https://www.hurl.it/#top to make a POST HTTP request to the Poloniex Exchange API.
Note that I have generated my Sign by going to https://www.freeformatter.com/hmac-generator.html#ad-output putting my SECRET and API_KEY into the given fields, and choosing the SHA512 algorithm.
I have filled out the fields at https://www.hurl.it/#top with the following (All fields are verbatim other than API_KEY and SECRET for obvious reasons):
Destination
POST: https://poloniex.com/tradingApi
Headers
Key: API_KEY
Sign: SECRET
Parameters
nonce: 0001
command: returnBalances
I am then given the error:
{"error":"Invalid API key\/secret pair."}
What am I doing wrong? Am I not following the API requirements for an HTTP request verbatim? Also I am not looking for any libraries/programming languages to use. I am looking to make this work using this website or something similar, because once I do, I will have what I'm looking for.
Note that I have generated my Sign by going to https://www.freeformatter.com/hmac-generator.html#ad-output putting my SECRET and API_KEY into the given fields, and choosing the SHA512 algorithm.
Api & secret are very sensitive data, so take care to:
- Never share your api key and secret on a tier website. (it could be store and be reuse)
- Never send a request containing your api key and secret in clear. (it could be intercepted by a MIM attack and/or your ISP and/or DPI)
Finally :
You may compute yourself (locally) the signature using a PHP wrapper recommended on the Poloniex Api documentation page
While I was reading about interaction with Amazon S3, I came to know that request authentication with Amazon AWS is done in 2 ways
HTTP Authorization:
Using the HTTP Authorization header is the most common method of providing authentication information
Query string parameters:
Using query parameters to authenticate requests is useful when you want to express a request entirely in a URL. This method is also referred as presigning a URL.
The question is in which situation should I prefer one method over the other. Do these two authentication methods have their own advantages and disadvantages? As a developer, by using query string parameters method I can presign the URL which enables the end users to temporarily access the Amazon S3 resources by entering the presigned URL in the web browser. Can I use HTTP Authorization method to achieve the same thing? If so which method is better to use and what are their respective limitations?
Can I use HTTP Authorization method to achieve the same thing?
Sometimes. The key difference is that, as a developer, you don't always have enough control over the user agent to inject a header. The most obvious example of this is a simple GET request launched by a web browser in response to the user clicking a link. In that situation, you don't have the a ability to inject an Authorization: header for the browser to send ... so pre-signing the URL is all you can do.
Importantly, there's no information in a signed URL that is considered sensitive, so there's no particularly strong motivation to use the header instead of a signed URL. Your AWS Access Key ID is not secret, and your AWS Secret can't be derived from the other elements and the signature in a computationally-feasible time frame, particularly if you use Signature Version 4, which you should. Signature Version 2 is not officially deprecated in older regions, but newer S3 never supported it and likely never will.
When you do control the user agent, such as in back-end server code, adding the header may be preferable, because you don't need to do any manipulation of the URL string you already have in-hand.
The overview in the first AWS page says what the difference is:
Except for POST requests and requests that are signed by using query parameters, all Amazon S3 bucket operations and object operations use the Authorization request header to provide authentication information.
Basically a POST is used for HTML forms (discussed at length in the Mozilla page). You would use forms whenever the request involves passing data to the remote server, versus just checking status. As noted in HTML method Attribute (W3Schools),
Never use GET to send sensitive data! (will be visible in the URL)
as distinguished from POST:
Appends form-data inside the body of the HTTP request (data is not shown is in URL)
I am using FineUploader to upload to S3. I have everything working including deletes. However, when I upload larger files that get broken into multi-part uploads, I get the following error in the console (debugging turned on):
Specific problem detected initiating multipart upload request for 0: 'The request signature we calculated does not match the signature you provided. Check your key and signing method.'.
Can someone point me in the right direction as what I should check for settings, or what additional info you might need?
Since you haven't included anything really specific to your setup, code, or the failing request, my best guess is that your server isn't returning a proper signature response for uploads made to the S3 REST API (which is used for larger files). You'll need to review that procedure for generating a response to this type of signature request.
Here's the relevant section from Fine Uploader's S3 documentation:
Fine Uploader S3 uses Amazon S3’s REST API to initiate, upload,
complete, and abort multipart uploads. The REST API handles
authentication by signing canonically formatted headers. This signing
is something you need to implement server-side. All your server needs
to do to authenticate and supported chunked uploads direct to Amazon
S3 is sign a string representing the headers of the request that Fine
Uploader sends to S3. This string is found in the payload of the
signature request:
{ "headers": /* string to sign */ }
The presence of this property indicates to your sever that this is, in
fact, a request to sign a REST/multipart request and not a policy
document.
This signature for the headers string differs slightly from the policy
document signature. You should NOT base64 encode the headers string
before signing it. All you must do, server-side, is generate an HMAC
SHA1 signature of the string using your AWS secret key and then base64
encode the result. Your server should respond with the following in
the body of an ‘application/json’ response:
{ "signature": /* signed headers string */ }