Firebase Admin SDK : Verifying ID tokens from the REST API - firebase

I'm trying to verify Id tokens received by signing in with the REST API for authentication by using the verifyIdToken(idToken) method in the Admin SDK but instead of getting the decoded token I get the error:
Firebase ID token has incorrect "iss" (issuer) claim. Expected "https://securetoken.google.com/"" but got "https://identitytoolkit.google.com/". Make sure the ID token comes from the same Firebase project as the service account used to authenticate this SDK. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
As I said above I'm getting my token from the REST API, so I was expecting this to work.
The response I get from the API is this:
{
"kind": "identitytoolkit#VerifyPasswordResponse",
"localId": "pu0yjIc8tnR85X2gERdtLx684DK2",
"email": "test#test.com",
"displayName": "",
"idToken": "<token-id>",
"registered": true
}
Is this considered a custom token? if so, how can I verify it?

As of Sep 2018, the issuer of the ID Token returned by REST API seems to be changed from https://identitytoolkit.google.com/ to https://securetoken.google.com/. And I can successfully verify this id token in firebase admin SDK.
[Edit]: The firebase admin SDK still fails to verify the Facebook ID Token returned by identitytoolkit's verifyAssertion REST API.

According to Google Developer
Calling the tokeninfo endpoint
An easy way to validate an ID token for debugging and low-volume use
is to use the tokeninfo endpoint. Calling this endpoint involves an
additional network request that does most of the validation for you,
but introduces some latency and the potential for network errors.
To validate an ID token using the tokeninfo endpoint, make an HTTPS
POST or GET request to the endpoint, and pass your ID token in the
id_token parameter. For example, to validate the token "XYZ123", make
the following GET request:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

Related

Error: Firebase ID token has no "kid" claim

Firebase documentation states that custom claims can be accessed like so:
admin
.auth()
.verifyIdToken(idToken)
.then((claims) => {
if (claims.admin === true) {
// Allow access to requested admin resource.
}
});
I have implemented Firebase auth following this sample project and tutorial. Specifically, the token is being decoded inside Next.JS' getServerSideProps here.
It's also worth mentioning that I'm running this project in development mode with Firebase Emulators.
So, on calling:
verifyIdToken(token)
I get this error message:
Error: Firebase ID token has no "kid" claim. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
Any idea where I'm failing?
---------- UPDATE ----------
The decoded token has this info:
{
"header":{
"alg":"none",
"typ":"JWT"
},
"payload":{
"email":"user#test.test",
"email_verified":false,
"auth_time":1626004181,
"user_id":"MY_USER_ID",
"firebase":{
"identities":{
"email":[
"user#test.test"
]
},
"sign_in_provider":"password"
},
"iat":1626004181,
"exp":1626007781,
"aud":"MY_FIREBASE_PROJECT_ID",
"iss":"https://securetoken.google.com/MY_FIREBASE_PROJECT_ID",
"sub":"SOME_KEY"
}
}

Getting 'EMAIL_NOT_FOUND' error when trying to get the token from Firebase

I am trying to get the firebase token through postman with email and password by using below API
https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={API_KEY}
Below is the body
{"email":"{YOUR_EMAIL_ADDRESS}","password":"{PASSWORD}","returnSecureToken":true}
I am using proper email and password which I used to log into firebase console. But I am getting EMAIL_NOT_FOUND error as below.
{
"error": {
"code": 400,
"message": "EMAIL_NOT_FOUND",
"errors": [
{
"message": "EMAIL_NOT_FOUND",
"domain": "global",
"reason": "invalid"
}
]
}
}
From the firebase document, we will get this error when "There is no user record corresponding to this identifier. The user may have been deleted."
But I am able to see the email under "Users and permissions" and the role as 'owner'. I am using the same email ID. Can anyone please help me to fix this issue.
You need to add the user in the authentication list:
https://console.firebase.google.com/project/*****/authentication/users
Firebase add user panel:

403 errors with keycloak API

I'm trying to use the Keycloak API (in node via keycloak-admin library) but I systematically get error 403.
I get successfully an access token via the library; by calling /auth/realms/master/protocol/openid-connect/token (on master realm) .
When I look inside my token, I seem to have the correct roles to be able to query the users :
{ "jti": "xx-..", "exp": 1585561478, "nbf": 0, "iat": 1585561418, "iss": "https://auth-mycompany.com/auth/realms/master", "aud": "mycompany-realm", "sub": "xx-..", "typ": "Bearer", "azp": "admin-cli", "auth_time": 0, "session_state": "xx-..", "acr": "1", "resource_access": { "mycompany-realm": { "roles": [ "view-users", "query-groups", "query-users" ] } }, "scope": "email profile", "email_verified": true, "name": "myname", "preferred_username": "myname", "given_name": "my name", "email": "myemail#mycompany.com" }
However , when I do a GET on https://auth-mycompany.com/auth/admin/realms/master/users or https://auth-mycompany.com/auth/admin/realms/mycompany/users ; I get 403 errors.
Maybe it's linked with the "aud" of my token ? Why do I get a token with "aud": "mycompany-realm" when I query master realm ?
Thanks for any help.
I eventually realize that this is due to the fact that I have implemented Port Restriction for admin endpoints. As described in the documentation, all endpoints starting with /auth/admin get a 403 response. Instead, these endpoints are accessible via another port (for example 9991) which is not accessible over the internet.
What I did to fix my issue : because both my Nodejs service and my keycloak server are running on the same kubernetes cluster, I change the authUrl of my keycloak server with its service name http://servicename.namespace.svc.cluster.local:9991/auth

How to send a message to the user who logged in through the telegram in website?

How to send a message to the user who logged in through the telegram in website?
Telegram Login for Websites
Telegram bots are a powerful communication tool, but until today they
couldn't start a conversation. Even if you wanted them to reach out to
you, you had to chat them up first.
and
Bot API 3.6
Added the new field connected_website to Message. The bot will receive a message with this field in a private chat when a user logs in on the bot's connected website using the Login Widget and allows sending messages from your bot.
After login user,my bot can not send message with use user_id,Even the OnMessage event is not fired.
How start a conversation by bot?
Thankful.
You answered your question yourself here :
Added the new field connected_website to Message. The bot will receive a message with this field in a private chat when a user logs in on the bot's connected website using the Login Widget and allows sending messages from your bot.
More descriptions:
After the user logged in with telegram login widget,you should wait for an update event (assuming you'r using Webhook method for your telegram bot). the update body should be something like this:
{
"update_id": 290285,
"message": {
"message_id": 12,
"from": {
"id": 117854,
"is_bot": false,
"first_name": "",
"last_name": "",
"language_code": "fa"
},
"date": 1549829158,
"chat": {
"id": "you need this to start conversation",
"type": "private",
"first_name": "user_firstname",
"last_name": "user_last name"
},
"connected_website": "the domain mapped to your bot"
}
from the "connected_website" filled you can realize this is a user logged in for the first time and save the chat id to start next conversations in future.
PS : I wonder why there is no documentation about this at telegram or at least I didn't found anything.
In my case I did not receive an update event as a webhook, like Ali Titan described.
But instead chat_id came to custom onauth js funcion:
{
"id': 100102379,
"first_name": "Guido",
"last_name": "Van Rossum",
"username": "guido",
"auth_date": 1642941713,
"hash": "568a5665500a389a754a1c04348ea1c0434d4b507b1920f3ca1ff017a1c04341"
}
In this example id is exactly chat_id you are looking for.
In other words, if you want to provide it to your backend, you should write something like:
<script async src="https://telegram.org/js/telegram-widget.js?15" data-telegram-login="samplebot" data-size="large" data-onauth="onTelegramAuth(user)" data-request-access="write"></script>
<script type="text/javascript">
function onTelegramAuth(user) {
$.ajax({
url: '/telegram_widget/login/',
method: 'POST',
contentType: "application/json; charset=utf-8",
data: JSON.stringify(user),
});
}
</script>
And then use this id to communicate with your user.

Get logged in user's calendarId

I want to retrieve calendar events of the logged in user. The API doc here suggests that I need to pass 'primary' as calendarId for the logged in user.
Therefore the URL becomes https://www.googleapis.com/calendar/v3/calendars/primary/
I am getting a 401 on this URL.
GET https://www.googleapis.com/calendar/v3/calendars/primary/ 401 ()
Can someone please suggest what am I doing wrong.
I think you need to pass a different calendarId (email address of a calendar). To get your calendarID, you can follow the steps specified here.
And to know about the error you encountered, here is the document about 401: Invalid Credentials.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization",
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
Suggested actions:
Get a new access token using the long-lived refresh token.
If this fails, direct the user through the OAuth flow, as described in Authorizing requests with OAuth 2.0.
If you are seeing this for a service account, check that you have successfully completed all the steps in the service account
page.

Resources