How to use Firebase Auth REST API using Google Apps Script? - firebase

I am trying to sign up users on Firebase Auth using Google Apps Script via the Firebase Auth REST API.
My code looks this.
var apiKey = "XXXX";
var url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=" + apiKey;
var options = {
method: 'post',
contentType: 'application/json',
email: "email#gmail.com",
password: "12345678",
returnSecureToken: true
};
var response = UrlFetchApp.fetch(url, options);
I am receving the following error.
{
"error": {
"code": 400,
"message": "ADMIN_ONLY_OPERATION",
"errors": [
{
"message": "ADMIN_ONLY_OPERATION",
"domain": "global",
"reason": "invalid"
}
]
}
}
How do I go about this?

Request body payload should be sent as a 'payload' property of the options object.
var payload = {
email: "sauravo14#gmail.com",
password: 12345678,
returnSecureToken: true
};
var options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload)
};

Related

Next Auth Credentials Provider - SignIn() and Mapping to my API Dto

I am using Next.js and Next Auth to talk to my backend C# ASP.NET API.
My API's response is the following DTO:
{
"data": {
"accessToken": "string",
"refreshToken": "string",
"email": "user#example.com",
"username": "string",
"roles": [
"string"
]
},
"success": true,
"message": "string"
}
I am having a hard time getting that info into the next auth session so that I can grab it with useSession().
I'd also like to be able to display the API "message" to the user in the login form. Incase their account is locked or whatever.
This is what I have:
[...nextauth].js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { API_URL } from "#/constants";
export const authOptions = {
// Configure one or more authentication providers
providers: [
// Add Your Providers Here
CredentialsProvider({
name: "Credentials",
credentials: {
username: { label: "Username", type: "text", placeholder: "jsmith" },
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
const { usernme, password } = credentials;
const body = JSON.stringify({
username,
password,
});
// Login request to our API.
const res = await fetch(`${API_URL}/Login`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=utf-8",
},
body: body,
});
const data = await res.json();
// Our API's response contains
/*
{
"data": {
"accessToken": "string",
"refreshToken": "string",
"email": "user#example.com",
"username": "string",
"roles": [
"string"
]
},
"success": true,
"message": "string"
}
*/
const user = {
success: data.success,
message: data.message,
email: data.data.email,
username: data.data.username,
accessToken: data.data.accessToken,
refreshToken: data.data.refreshToken,
roles: data.data.roles,
};
// EVERYTHING TO HERE IS GOOD!
// I CAN GET THE user OBJECT FILLED.
if (res.ok && user) {
return user; //<---- is this actually returning the full user object to the session?
} else {
return null;
}
},
}),
],
pages: { signIn: "/login" },
};
export default NextAuth(authOptions);
Navbar Links:
<Nav.Link as={Link} href='/login' onClick={() => signIn()}>Login</Nav.Link>
<Nav.Link as={Link} href='/signout' onClick={() => signOut({callbackUrl: '/'})}>Signout</Nav.Link>
Login form:
// Get data from the form.
const nextAuthSettings = {
username: event.target.username.value,
password: event.target.password.value,
redirect: true,
callbackUrl: "/dashboard",
};
// Send the form data to Next Auth
const result = await signIn("credentials", nextAuthSettings);
// Error Handling
// THIS DOES NOT WORK
// I don't think signIn() returns a copy of the user object unfortunately...
if (!result.success) {
// Display the API Error Message On The Page
setErrorMsg(result.message);
}
And then in various pages, when I want to access the user object I am doing this :
import { useSession } from "next-auth/react";
const { data: session } = useSession();
// This only shows the email
<span>{session?.user.email}</span>;
// It looks like a JWT or something when I console log it
{
"user": {
"email": "users#email.com"
},
"expires": "2023-03-16T12:39:28.120Z"
}
Any help appreciated!
I need to be able to access the user object my API is returning throughout my app.
At the moment I'm just getting this session.user.email and nothing else ??
it's like I am not mapping the API's response to whatever Next Auth wants me to create...
you have to use callbacks :
callbacks: {
async jwt({ user, token }) {
// update token from user
if (user) {
token.user = user;
}
// return final_token
return token;
},
async session({ session, token }) {
// update session from token
session.user = token.user;
return session;
},
},
Now you can access your session with useSession() and your token with getToken()

Fauna returning 'unauthorized' when using Auth0 as a third party access provider

I am trying to integrate Fauna and Auth0 into my Vue 3 app.
To achieve that I am following this Auth0 guide and this youtube video.
In short, I have configured Auth0 as a Provider inside Fauna. And I am sending the Auth0 generated JWT token as the Fauna secret. Fauna should then decode the JWT and give access to the call.
To test it out my code fetches some dummy "products" data from Fauna and prints it to the console.
But when I make the call it returns as unauthorized.
What am I doing wrong?
Here is the script inside my Vue component that is making the call:
import { defineComponent, inject } from "vue";
import { query as q, Client } from "faunadb";
export default defineComponent({
name: "Api",
setup() {
let apiMessage = null;
let executed = false;
const auth = inject("Auth");
const callApi = async () => {
const accessToken = await auth.getTokenSilently();
console.log(accessToken);
try {
const client = new Client({ secret: accessToken });
const { Paginate, Documents, Collection } = q;
const data = await client.query(
Paginate(Documents(Collection("products")))
);
console.log(data);
apiMessage = data;
executed = true;
} catch (e) {
console.log(e);
apiMessage = `Error: the server responded with '${e.response.status}: ${e.response.statusText}'`;
}
};
return {
callApi,
};
},
});
Here is a copy of the unauthorized response object that is returned:
{
"name": "Unauthorized",
"message": "unauthorized",
"description": "Unauthorized",
"requestResult": {
"method": "POST",
"path": "",
"query": null,
"requestRaw": "{\"paginate\":{\"documents\":{\"collection\":\"products\"}}}",
"requestContent": {
"raw": {
"paginate": {
"raw": {
"documents": {
"raw": {
"collection": "products"
}
}
}
}
}
},
"responseRaw": "{\"errors\":[{\"code\":\"unauthorized\",\"description\":\"Unauthorized\"}]}",
"responseContent": {
"errors": [
{
"code": "unauthorized",
"description": "Unauthorized"
}
]
},
"statusCode": 401,
"responseHeaders": {
"content-length": "65",
"content-type": "application/json;charset=utf-8",
"x-txn-time": "1634006015704445"
},
"startTime": 1634006014934,
"endTime": 1634006015885
}
}
Figured it out.
The client has to be initiated with some other values, most importantly is the domain value.
var client = new faunadb.Client({
secret: 'YOUR_FAUNA_SECRET',
domain: 'db.fauna.com',
// NOTE: Use the correct domain for your database's Region Group.
port: 443,
scheme: 'https',
})

How to get, store and reuse firebase token in cypress api automated testing

after sending in body "email" and "password" https://identitytoolkit.googleapis.com/ returns a few objects in the response.
One of them is "idToken": with a value of the token.
What do I need?
I need to get this token, store it in variable and reuse it in further tests.
So far I prepared something like this:
it("Get a fresh admin firebase token", () => {
cy.request({
method: "POST",
url: "https://identitytoolkit.googleapis.com/...",
body: {
"email": "myUsername",
"password": "myPassword",
"returnSecureToken": true
},
headers: {
accept: "application/json"
}
}).then((responseToLog) => {
cy.log(JSON.stringify(responseToLog.body))
}).then(($response) => {
expect($response.status).to.eq(200);
})
})
})```
Above code works, but cy.log() returns the whole body response. How can I separate only idToken and reuse it in my next API scenarios?
Considering that idToken in in response body so inside then() you can directly wrap the value and save it using an alias and then use it later.
it('Get a fresh admin firebase token', () => {
cy.request({
method: 'POST',
url: 'https://identitytoolkit.googleapis.com/...',
body: {
email: 'myUsername',
password: 'myPassword',
returnSecureToken: true,
},
headers: {
accept: 'application/json',
},
}).then((response) => {
cy.wrap(response.body.idToken).as('token')
})
})
cy.get('#token').then((token) => {
cy.log(token) //logs token or Do anything with token here
})
In case you want to use the token in a different it block you can:
describe('Test Suite', () => {
var token
it('Get a fresh admin firebase token', () => {
cy.request({
method: 'POST',
url: 'https://identitytoolkit.googleapis.com/...',
body: {
email: 'myUsername',
password: 'myPassword',
returnSecureToken: true,
},
headers: {
accept: 'application/json',
},
}).then((response) => {
token = response.body.idToken
})
})
it('Use the token here', () => {
cy.log(token) //prints token
//use token here
})
})

Firestore ID token from user signin fails to authenticate in REST API calls

I have some data that I have created in my Firestore. I am trying to access them using the REST API. But I am getting an authentication error. I am doing the following:
According to the Cloud Firestore documentation, I can
"Generate a Firebase ID token using the Firebase Authentication REST
API."
To get the idToken I am signing in a valid user in the following way:
const API_KEY = 'my API key'
const URL_GET_TOKEN_BY_SIGN_IN = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${API_KEY}`;
const getTokensBySigningIn = () => {
return new Promise(async (resolve, reject) => {
const res = await fetch(URL_GET_TOKEN_BY_SIGN_IN, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: `registered_user_email#somedomain.com`,
password: "valid_password",
returnSecureToken: true,
}),
}).catch((err) => {
reject(err);
});
const resData = await res.json().catch((err) => {
reject(err);
});
resolve(resData);
});
};
The returned promise resolves with an object of the form:
{
"kind": "identitytoolkit#VerifyPasswordResponse",
"localId": "ZgnICJLhiJM5... some local id",
"email": "registered_user_email#somedomain.com",
"displayName": "",
"idToken": "eyJhbGciOiJSUzI1N... a 985 char long token",
"registered": true,
"refreshToken": "AGEhc0Dq9fodOAAs_on5A... a 298 char long token",
"expiresIn": "3600"
}
So far so good. Now I take the idToken from the response and try to use it in the request headers (as the documentation says):
const getDocsFromFirestore = async () => {
const responseSignin = await getTokensBySigningIn();
const URL_GET_FIRESTORE_DATABASES = `https://firestore.googleapis.com/v1/projects/${PROJECT_ID}/databases/documents`;
const response = await fetch(URL_GET_FIRESTORE_DATABASES, {
method: "GET",
headers: {
Authorization: `Bearer ${responseSignin.idToken}`,
},
});
const responseFirestoreDB = await response.json();
console.log(responseFirestoreDB);
};
But now, if I call the getDocsFromFireStore() function, I get the following error:
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
Any help?
Note that, I have set the requirements of auth in the Firestore rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if
request.auth != null;
}
}
}
You are not specifying the database that you are looking into. Compare your API request URL with the one in the documentation:
/projects/YOUR_PROJECT_ID/databases/(default)/documents/cities/LA
^^^^^^^^^
Try changing your request URL to:
const URL_GET_FIRESTORE_DATABASES = `https://firestore.googleapis.com/v1/projects/${PROJECT_ID}/databases/(default)/documents`;
That being said, there's no such endpoint. Are you trying to list documents of a specific collection? Then try specifying the collection name:
https://firestore.googleapis.com/v1/projects/${PROJECT_ID}/databases/(default)/documents/users;
^^^^^
You can find more about REST API endpoints in the documentation.

Paypal refund API gives UnAuthorized Error

const { paymentId } = req.body;
const refundURI = `https://api.sandbox.paypal.com/v2/payments/captures/${paymentId}/refund`;
// get access token
const { access_token } = await generateToken();
// console.log(JSON.stringify(access_token));
const refundObj = await Axios.post(refundURI, {
headers: {
Accept: `application/json`,
Authorization: `Bearer ${access_token}`,
},
body: JSON.stringify({
amount: {
currency_code: "USD",
value: "10.00",
},
}),
});
I am trying to refund a paypal payment .I am generating access token but still its giving unAuthorized with 401 status code .

Resources