Firebase ID token - JWT::VerificationError Exception: Signature verification raised - ruby-on-rails

Validating the firebase id token in ruby on rails with library "firebase_id_token".
Once I got the valid token from the front-end with the google_sign_in library and sending it to the backend, it always prompts as "JWT::VerificationError (Signature verification raised)". Even though I have checked in jwt.io, where I could able see the information of payload and header but unable to verfiy the signature.
firebase_id_token.rb
FirebaseIdToken.configure do |config|
config.project_ids = ["project_id"]
config.redis = Redis.new(host: "localhost", port: 6379)
end
FirebaseIdToken::Certificates.request
Also, I checked the kid key is a valid one on this link
https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com
I have been debugging the code for more than a week, Please anyone assist with this issue.
PS: I have tested the code with a valid token and not an expired one.

Google sign-in returns an OAuth2 token, not a JWT as far as I know, and definitely not a Firebase ID token. If you are passing this Google sign-in token to your backend code, it correctly gets rejected when you try to verify it as a Firebase ID token.
To get a Firebase ID token, you need to sign-in to Firebase with the Google sign-in token (by calling signInWithCredential) and then pass the resulting Firebase ID token to your backend code.

Related

Why need front end stores firebase token?

I am making a web application. Front side is react, server side is rails api and I use firebase authentication.
Now, I get firebase token and set authorization header whenever calling rails api as below.
client.interceptors.request.use(
async (config) => {
config.headers['Content-type'] = 'application/json'
config.withCredentials = true
var token = await firebaseApp.auth().currentUser?.getIdToken()
config.headers['Authorization'] = `Bearer ${token}`
return config
},
(error: AxiosError) => {
throw new Error(error.message)
}
)
But, I found some ways to store token, unsafe local storage, http only cookie.
Why need front end stores firebase token? Is it bad to get the token every time calling rails api?
Firebase ID Tokens are basically JWT, signed by Firebase.
Now imagine a scenario where you need to identify the user in your server. You will probably pass the user's UID in the HTTP Request, which is not safe as that can be easily bruteforced unless you have some sort of rate limiting in your server.
What I meant by signed?
A JWT looks something like: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
The data stored in above JWT is:
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
You need to verify those Firebase IDTokens using Firebase Admin SDK. I don't know if that works with Ruby but worth checking the link above.
Verifying those will either return an object with user auth info or an error if that is an invalid JWT.
You must always pass this JWT in you REST requests to your server because these cannot be bruteforced. Anyone can make a JWT (IDToken) with same content but they don't know your signature. They will need your Firebase Service Account credentials to do so.
Also, JWTs expire eventually (I assume after an hour). So it's not bad to get token again and again. That's what they are meant for. Short term access.
I recommend you to watch this JWT Tutorial.
Just be sure to pass the idToken to your REST API to authenticate users and not their UID.

Sign In With Apple refresh token validation only access token returned

I'm using the AppleAuth npm package in my server to submit token requests to Apple's servers during the sign in with Apple process. (This is based off the sample server code provided with the sign_in_with_apple package in pub.dev) I have no issues submitting the authorization code to get my first access and refresh tokens.
However, when trying to test how my app would get a new refresh token, when I submit a POST request to https://appleid.apple.com/auth/token with the grant_type set to refresh_token the response I get is different than from having the grant_type set to authorization_code.
I looked at the source code of the package, and for its AppleAuth(myConfig).refreshToken(myRefreshToken) (<- pseudo code lol) the only difference in the POST payload is:
{
grant_type: 'refresh_token', // instead of grant_type: 'authorization_code'
refresh_token: refreshToken, // instead of code: authorizationCode
... // other params
}
While the initial request with authorization code returns both an access token and a refresh token, for some reason the refresh token request is only returning the access token. I really don't think it's the package causing the error, nor can I see how my code would be the source either, since the above code is the only difference.
I tried passing the access token that it returns in a new refresh token request in order to test that I can get new refresh tokens whenever necessary in the future, but it returns a 400 status error.
Am I missing something here? Is there a reason the refresh token request returns no new refresh token? Or am I missing something entirely about how the process/flow is supposed to work? I am trying to do this for the "check the refresh token once daily to confirm the user is still in good standing with Apple's servers" part of the process.
I've really been stuck on what to do at this point. I can save the identity_token.sub field in my database to check whether my user is signed in, but of course I want to make sure my user's apple ID is still valid with apple, and that they haven't revoked access. Could it be that because I tried to get a new refresh_token too soon Apple only returned the access_token?
Oh also, the app itself is a Flutter app and I am testing all of this on my iPhone 11 so it's not an Android/Web flow.
Whether you get a new 'rolling / rotating' refresh token in a refresh token grant response is generally vendor specific:
You may get a new refresh token occasionally but not always
The primary purpose of this message is to get a new access token, not a new refresh token
In terms of token handling, the client should update its tokens similarly to the saveTokens method in this sample of mine.
I've not used Sign In with Apple but I suspect proceeding as follows would be the simplest solution:
Keep access tokens short lived: no more than 60 minutes
This forces a frequent token refresh, which by default is very quick
If the user's Apple Id is revoked I would expect this to return an invalid_grant response

Refreshed OAuth2 token has invalid signature (Azure AD OAuth2)

I'm trying to create an authentication flow where the user's access token is kept in a server-side session along with the refresh token, and when the token expires it is renewed if the session is still valid. However, the token I get back from Azure AD after refresh has an invalid signature, when verifying it with the same method as the original token.
Here's a runnable gist that illustrates the problem: https://gist.github.com/tlycken/fdaf47dc31e03de43a1a07fbbea2ab91
What I'm doing is basically this:
When the user requests a page, check for a session. If none exists, redirect to /auth which redirects to Azure AD, and when I'm returned I have a valid token which I store in the session.
Verify the token from the session using jwks-rsa. (This normally works fine, so I'm purposely adding something to the token string to make the signature invalid in the test code.)
If token verification failed, and there is a refresh token on the session, try to fetch a new token using that refresh token. This request normally returns with status 200 OK and a new set of access/refresh tokens.
Verify the new access token using the same code as was used to verify the old one (now without garbling the token). This should work, IIUC, but it fails with the error invalid signature.
Why does my newly refreshed token not pass verification?
Update:
I was able to create a simpler flow for reproducing this; the gist has been updated. It now does the following (printing these messages, along the way):
no session, redirecting to /auth
successful auth callback, redirecting to /
verifying old token
decoded user id e7f02a6e-510c-430d-905c-f8a0e63206c2
refreshing
fetching /me with renewed token
got user id e7f02a6e-510c-430d-905c-f8a0e63206c2
verifying new token
token verification failed: invalid signature
In addition to validating the token myself, I now also send a request to Azure with it, hoping that such a request would fail for an invalid token. But it passes!
You're code is using the v1 Endpoint to obtain the initial access token but the v2 Endpoint to exorcise the refresh token. These two endpoints operate differently. In particular, the v1 Endpoint uses "resource" while v2 uses "scopes".
The reason this is happening is your calling v1 explicitly but relying on the v2 /openid-configuration for the Refresh Token endpoint.
To correct this, change line 19 of refresh-auth-token.js to
const configResponse =
await fetch(`https://login.microsoftonline.com/${AZURE_TENANT}/.well-known/openid-configuration`)

How to request access token from Battle.net OAuth with authorization code?

I have a hobby project in mind to use battle.net login. I'm wondering how I can obtain the access token from the API after receiving the authorization code.
This is Oauth flow question rather than a battle.net question.
Currently I can successfully authorize the user for my app which is registered in dev.battle.net and then I try to use the authorization code returned from the battle.net login to obtain the access token by sending a request to https://<region>.battle.net/oauth/token.
However I keep receiving this error:
{
"error": "unauthorized",
"error_description": "An Authentication object was not found in the SecurityContext"
}
I use postman extension to send post requests to that uri. I authenticate my request with my client id and secret. I pass redirect_uri (https://localhost), granty_type (authorization_code), code(the code returned from the previous authorization step). However I keep getting the error above.
I couldn't find much about battle.net online. There are other oauth related help articles but couldn't really find my way.
Wondering if you can help me with this easy stuff. I'm just wondering what I'm skipping here.
Here is the documentation:
https://dev.battle.net/docs/read/oauth
https://localhost is added in my mashery dev account's app settings.
Me again, I resolved this problem after trying almost every combination in the universe:)
Steps to apply:
Don't use the same authorization token for different access token trials, they are not valid
Always use https on every domain you test including localhost, you
redirect_uri must be https as well.
You must use the "basic authentication" in the header of your POST request while requesting the token from the authorization code you obtained from the previous step.
This is one of the most important ones: For requesting token, Pass redirect_uri, client key and secret as POST form parameters to the authenticated request. This is interesting because it's already an authenticated request; why would i need to pass my secret again? Anyways, that's how it works.
Here are the full text:
http://hakanu.net/oauth/2017/01/26/complete-guide-of-battle-net-oauth-api-and-login-button/
This is working prototype:
https://owmatch.me
Thanks.

Getting invalid oauth access token: where is the token I need?

I would like help obtaining/locating the correct access_token value for an API call.
I'm configuring an application that wants to search Facebook using the graph-api search request at https://graph.facebook.com/fql, for which I need an access_token. The application is a backend server so there's no UI and no users.
I registered a new 'app' using the developer pages 'Create a New App' link, so I now have an app at: https://developers.facebook.com/apps/<> and from that I get an 'app secret' token. Digging into the Advanced settings page for the app there is also a Client token.
However using either token results in the following JSON error:
{"error":{"message":"Invalid OAuth access token.","type":"OAuthException","code":190}}
Can anyone point me to where I've gone wrong?
==
The following 'curl' request demonstrates the command working correctly, but it's only usable token-less like this occasionally, so the app needs &access_token=...stuff... adding to the parameters.
$ curl 'https://graph.facebook.com/fql?q=select%20url,%20share_count,%20like_count,%20comment_count,%20click_count,%20total_count%20from%20link_stat%20where%20url%20=%20"http%253A%252F%252Felifesciences.org%252Fcontent%252F2%252Fe01233"'
{"data":[{"url":"http\u00253A\u00252F\u00252Felifesciences.org\u00252Fcontent\u00252F2\u00252Fe01233","share_count":0,"like_count":0,"comment_count":0,"click_count":0,"total_count":0}]}
The 'app secret' and 'Client token' will not work.
What you need is an Access Token, refer to this.

Resources