My questions is regarding AWS Cognito SDK. My front-end authenticates the user with amplify /cognito and sends the token in the header to my backend.
I have successfully used cognitoidentityserviceprovider.getUser() to get user attributes on my backend nodejs app, but without any permissions!
I am using a restricted user with only S3 and SES permissions on my API, but I am just surprised, the getUser() call just decode the JWT token without any authorisation? and if so, can anyone decode all user attributes from my jwt token using aws-sdk?
I also removed the API key entirely on the backend, just to see and it was still able get the user object successfully. Is this not a security risk?
Code:
const aws = require('aws-sdk');
var provider = new aws.CognitoIdentityServiceProvider();
const user = await provider.getUser( {AccessToken: jwtToken}).promise();
return user;
Related
Currently I'm struggling with that kind of issue while obtaining an access token for accessing Gmail user mailboxes. I'm trying to get an access token using Google Auth Library for Node.js. using that kind of code snippet:
const {GoogleAuth} = require('google-auth-library');
async function main() {
const auth = new GoogleAuth({
scopes:
'https://mail.google.com/',
});
const client = await auth.getClient();
const token = await auth.getAccessToken();
console.log(client);
console.log(token)
}
main().catch(console.error);
The thing is that I get the access token with the default list of scopes: scope: 'https://www.googleapis.com/auth/cloud-platform openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/accounts.reauth'
When I try to log in with ADC using gcloud auth application-default login --scopes='https://mail.google.com/'
I'm being redirected to the google authentication page to choose the account to provide Google Auth Library access to. As soon as I choose the account there appears the screen with that being shown "The application is blocked"
So, guys, is there a way to grant access to Node.js Google Auth Library client library to Gmail mailboxes of the user authenticated by ADC (Application Default Credentials).
I know about impersonation the service account methods and OAuth2.0 authentication, but is it possible to get access token using scoped ADC? And how to make those ADC customly scoped with (https://mail.google.com) access.
This question already has answers here:
Firebase admin on backend for verifyIdToken and use Firestore
(1 answer)
Restrict firestore access to admin-sdk
(2 answers)
Closed 1 year ago.
Firestore is amazing for creating serverless applications but I'm currently trying to use firestore as the primary system for my REST API. I'd like to be able to create sessions using a rest endpoint and passing token's to and from the client. I'd like to be able to use these tokens to make Authenticated calls and have firebase auth automatically handle database rules through the rules I've set as if I were using the firestore client sdk.
I am familiar with Firebase Admin but for obvious reasons I can't use that for Authenticated requests, at least not directly. I was wondering if there was a "Firebase-Admin" where I can pass a token.
Yes, there is Firebase Admin SDK which supposed to be used in secure environments like Cloud functions or your own server. It uses a service account and has full access to your Firebase project's resources and does not obey any security rules.
That being said you need to manually authenticate your users and check if they are allowed to access the resource that they are requesting. You must pass the Firebase ID Token in your REST API requests in headers or body (I usually pass it in authorization header as 'Bearer <firebase_id_token>'). You must not pass the UID of user itself under any circumstances.
Follow these steps to get Admin SDK up and running:
1. Installing the Admin SDK:
npm install firebase-admin
# yarn add firebase-admin
2. Create a middleware to verify the ID Tokens:
const express = require("express")
const app = express()
const admin = require("firebase-admin")
admin.initializeApp(...) // <-- use the service account to initialize
app.use(async function(req, res, next) {
const {authorization} = req.headers
if (!authorization) return res.sendStatus(401)
const decodedToken = await admin.auth().verifyIdToken(authorization)
console.log(decodedToken)
next()
})
// other endpoints
app.listen(3000)
The decodedToken contains user's UID, custom claims and other metadata. You can read more about that in the documentation.
You can download your Service Account Key from here: https://console.firebase.google.com/project/_/settings/serviceaccounts/adminsdk
Firebase generates the ID Token (Access Token) and a Refresh Token when a user logs in. You just need to pass that access token in your request. You can use the getIdToken method to get it.
async function callAPI() {
const idToken = await firebase.auth().currentUser.getIdToken()
const response = await fetch("url", {headers: {authorization: idToken}})
}
I have created an App using the Parse server, and have now decided to implement some aspects of firebase into my app. Im trying to accomplish this by doing the signInWithCustomToken method in swift on ios. Im calling a rest service to generate a firebase token, and then signing in with that token returned upon valid sign in on my current auth system. However, the token being generated appears to have an invalid signature when pasting it into jwt.io. The environment that im using is node based (inside the parse server). It seems very simple and i have followed the firebase instrucutions/poured over questions on this over the last few days and im really not sure what im doing wrong! Heres my rest service on how i generate the token, i initialize the server with this method:
Parse.Cloud.define("initServer", function(request, response){
var admin = require('firebase-admin');
var serviceAccount = require('/home/bitnami/apps/parse/htdocs/firebase/serviceAccountKey.json');
console.log(serviceAccount);
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://urabo-acb7a.firebaseio.com'
});
response.success("Server Init OK");
});
this is the post method i call to generate the token from firebase-admin sdk:
Parse.Cloud.define("generateFirebaseToken", function(request, response) {
var admin = require('firebase-admin');
admin.auth().createCustomToken(request.params.uid)
.then(function(customToken) {
// Send token back to client
response.success(customToken);
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
});
And of course I went into the firebase console and generated the private key, and then scp'd it over to my server. Im not really sure why this is not working, it generates a token it just doesnt appear to be valid or linked to my account. Am i missing some weird encoding issue or something with the token? Does anyone have insight on this?? Thanks so much!
—The main question is are your users signing in to the REST service through your app and then you are also trying to re-authenticate them again with the token generated in your system?
—If they will be accessing further REST functions once authenticated, then why not authenticate them successfully when 'a' token is returned?
—Usually token usage or handling is restricted by the API providers. Another option is instead of involving user auth directly with the API service, have a separate auth system — the usual SignIn process and then make API calls based on the requested API feature. That way your app is interacting with the APIs and users remain at the front end.
I would like to authenticate and keep sessions via NodeJS with Firebase. Client can't directly communicate with Firebase.
In short:
Client (browser) <----> NodeJs(firebase-admin) <----> Firebase
I created Firebase client in NodeJS, then I used login method:
var firebaseClient = require('firebase');
firebaseClient.initializeApp(config)
firebaseClient.auth().signInWithEmailAndPassword(req.body.email, req.body.password).catch(function(error){
console.log(error);
})
and then I created route to check authenticated user:
app.get('/check',function(req,res){
var user = firebaseClient.auth().currentUser
console.log(user)
})
This method only allows me keep 1 previously logged user.
I would like to use firebase-admin, but I don't know how to keep session and authenticate users
You can authenticate clients on their respective devices/browsers using the client SDK, and them get them to send an ID token to a backend service written using firebase-admin (the admin SDK). The admin SDK provides methods for validating ID tokens sent by clients: https://firebase.google.com/docs/auth/admin/verify-id-tokens
I know this issue was asked a lot here, but I still cannot seem to find the exact answer that can solve my problem.
I wish to access Firebase using REST calls, by adding an access_token param.
The access_token is created using the Node.js Admin SDK, using the following code:
var admin = require("firebase-admin");
var serviceAccount = require("./pk.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://XXX.firebaseio.com"
});
var uid = "1234";
admin.auth().createCustomToken(uid)
.then(function(customToken) {
// Send token back to client
console.log("Token: "+customToken);
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
The problem is that if I take the token created from Node.js and use it my REST call, I get an Unauthorized request error.
I have read in some questions that people added the scope param when issuing the token, but have not found a way to do that with Node.js Admin SDK.
Google's docs are not so detailed with this issue. Any idea what I might try to resolve this one?
The token you are using to authenticate to the Firebase REST API is not the correct type of token. You are using a Firebase Auth custom token, which can only be used to authenticate one of the Firebase client SDKs via the signInWithCustomToken() method as explained in Sign in using custom tokens on clients.
In order to authenticate to the Firebase REST API, you have two options: Firebase ID tokens (for user-based access) or Google OAuth2 access tokens (for admin access).
Authenticate with Firebase ID Tokens
See Retrieve ID tokens on the client for an explanation of how to retrieve access tokens in the various Firebase client SDKs. You can also exchange a Firebase custom token for an ID token and refresh token pair via an undocumented REST API:
Endpoint: https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=<API_KEY>
Method: POST
Request Body: { "token": <CUSTOM_TOKEN>, "returnSecureToken": true }
<API_KEY> is the same API key you get from your Firebase Console that you use in the Firebase clients. <CUSTOM_TOKEN> is a Firebase custom token.
Since ID tokens expire after an hour, you will need to use the refresh token to refresh them via this other undocumented REST API:
Endpoint: https://securetoken.googleapis.com/v1/token?key=<API_KEY>
Method: POST
Request Body: { "refresh_token": <REFRESH_TOKEN>, "grant_type": "refresh_token" }
<API_KEY> is the same API key as before. <REFRESH_TOKEN> is the refresh token from the previous API call.
Once you have an ID token, you can pass that to the REST API via the auth query parameter to authenticate a request. The request respects Firebase Security Rules as if the end user logged into the client was making the request.
Authenticate with Google Access Tokens
To authenticate with a Google OAuth2 access token, the first thing you need to do is get one. See Retrieving an access token for an explanation of how to do this. It only currently includes a Java example, but this is possible in many languages, including Node.js. Once you have an ID token, you can pass that to the REST API via the access_token query parameter to authenticate a request. The request will be made with admin access, overriding all Firebase Security Rules and granting full read and write access.