token generated for cloud function gives 401 - node.js

I am trying to generate JWT token from GCP service account as below:
import jwt from 'jsonwebtoken';
import axios from 'axios';
import config from ('../../config.json)
export const getJwt = async (req, res) => {
const token= jwt.sign({
'iss':config.client_email,
'sub':config.client_email,
'aud':'https://www.googleapis.com/oauth2/v4/token',
'scope':'https://www.googleapis.com/auth/cloud-platform',
'iat':parseInt(Date.now() / 1000),
'exp':parseInt(Date.now() / 1000) + 60 * 60,
},
config.private_key,
{
algorithm:'RS256',
header:{
'kid':jsoncontent.private_key_id,
'typ':'JWT',
'alg':'RS256'
},
}
);
const request = await axios.get(FUNCTION-URL,
{
headers: {
'Authorization': `Bearer ${token}`,
'X-Goog-User-Project': PROJECT_ID
}
}).then(response => {
console.log("response",response.data)
}
)
};
It gives me 401 unauthorized error. I validated JWT, It says invalid signature.
Note: I dont want to use google-auth-library for some reason

Related

The accessToken I am getting from Auth0/NextJs not working on Routes

I am using #auth0/nextjs-auth0 for my nextJs login.
This is my /[auth0].js code:
import { handleAuth, handleLogin } from "#auth0/nextjs-auth0";
export default handleAuth({
login: handleLogin({
authorizationParams: {
audience: process.env.AUDIENCE,
}
})
});
After login, I am calling the getAccessToken() and what I get as token doesn't work with my endpoint. But when I copy test accessToken from auth0 dashboard, it will work.
import { getAccessToken, withApiAuthRequired, getSession } from "#auth0/nextjs-auth0";
export default withApiAuthRequired(async function users(req, res) {
try {
const { accessToken } = await getAccessToken(req, res);
const {user} = await getSession(req, res);
console.log("with access token …", accessToken);
const response = await fetch("http://localhost:7000/auth", {
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
method: "GET",
The response I always get is 401, Unathorized.
What am I doing wrong?

Svelte: Hooks.js file is not getting recently created cookies

Someone knows why my hooks.js file not getting recently created cookies
When I do login with discord api in my svelte website, the cookies are created and the hooks only get it minutes after.
Someone can help me please?.....
I'm using parts of the medium discord Oauth2 svelte example
import cookie from 'cookie';
const DISCORD_API_URL = import.meta.env.VITE_DISCORD_API_URL;
const HOST = import.meta.env.VITE_HOST;
/** #type {import('#sveltejs/kit').GetSession} */
export async function getSession(req) {
const cookies = cookie.parse(req.request.headers.get("cookie") || '');
console.log(cookies)
// if only refresh token is found, then access token has expired. perform a refresh on it.
if (cookies.disco_refresh_token && !cookies.disco_access_token) {
console.log("Tem o refresh mas não tem o acess")
const discord_request = await fetch(`${HOST}/api/refresh?code=${cookies.disco_refresh_token}`);
const discord_response = await discord_request.json();
if (discord_response.disco_access_token) {
console.log('setting discord user via refresh token..')
const request = await fetch(`${DISCORD_API_URL}/users/#me`, {
headers: { 'Authorization': `Bearer ${discord_response.disco_access_token}` }
});
const response = await request.json();
if (response.id) {
return {
user: {
// only include properties needed client-side —
// exclude anything else attached to the user
// like access tokens etc
...response
}
}
}
}
}
if (cookies.disco_access_token) {
console.log('setting discord user via access token..')
const request = await fetch(`${DISCORD_API_URL}/users/#me`, {
headers: { 'Authorization': `Bearer ${cookies.disco_access_token}`}
});
// returns a discord user if JWT was valid
const response = await request.json();
if (response.id) {
return {
user: {
...response
}
}
}
}
// not authenticated, return empty user object
return {
user: false
}
}
My Auth callback file:
const DISCORD_CLIENT_ID = import.meta.env.VITE_DISCORD_CLIENT_ID;
const DISCORD_CLIENT_SECRET = import.meta.env.VITE_DISCORD_CLIENT_SECRET;
const DISCORD_REDIRECT_URI = import.meta.env.VITE_DISCORD_REDIRECT_URI;
/**
* #type {import('#sveltejs/kit').RequestHandler}
*/
export async function get({ url }) {
// fetch returnCode set in the URL parameters.
const returnCode = url.searchParams.get("code");
console.log('returnCode =>', returnCode);
// initializing data object to be pushed to Discord's token endpoint.
// the endpoint returns access & refresh tokens for the user.
const dataObject = {
client_id: DISCORD_CLIENT_ID,
client_secret: DISCORD_CLIENT_SECRET,
grant_type: 'authorization_code',
redirect_uri: DISCORD_REDIRECT_URI,
code: returnCode,
scope: 'identify email guilds'
};
// performing a Fetch request to Discord's token endpoint
const request = await fetch('https://discord.com/api/oauth2/token', {
method: 'POST',
body: new URLSearchParams(dataObject),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
const response = await request.json();
console.log(response)
if (response.error) {
console.log('redirect to / due error');
return {
headers: { Location: '/' },
status: 302
}
}
// redirect user to front page with cookies set
const access_token_expires_in = new Date(Date.now() + response.expires_in); // 10 minutes
const refresh_token_expires_in = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days
console.log('redirect to /logged with cookies');
return {
headers: {
'set-cookie': [
`disco_access_token=${response.access_token}; Path=/; HttpOnly; SameSite=Strict; Expires=${access_token_expires_in}}`,
`disco_refresh_token=${response.refresh_token}; Path=/; HttpOnly; SameSite=Strict; Expires=${refresh_token_expires_in}`,
],
Location: '/'
},
status: 302
}
}

Expressjs: google-auth-libary id-token verification "token used too late number > number..."

I have tried to add google auth login for my reactjs/expressjs web app. On the frontend I am using the react-google-login package:
import React from "react"
import { GoogleLogin } from "react-google-login"
import { useHistory } from "react-router-dom"
const axios = require('axios')
export default function LoginButton() {
let history = useHistory()
const { REACT_APP_GOOGLE_CLIENT_ID, REACT_APP_API_URL } = process.env
const onSuccess = async (response) => {
console.log(response)
const data = { token: response.tokenId }
const res = await axios.post(REACT_APP_API_URL + "/auth/google", data, {
'Content-Type' : 'text/json'
})
.then((res) => {
history.push('/home')
})
.catch((err) => {
console.log("[LOGIN FAILED]")
})
}
const onFailure = (response) => {
console.log(response)
}
return(
<GoogleLogin
clientId={REACT_APP_GOOGLE_CLIENT_ID}
buttonText="Log in with Google"
onSuccess={onSuccess}
onFailure={onFailure}
cookiePolicy={'single_host_origin'}
/>
)
}
From what it seems I am getting the correct data from this button. I am sending the token to the expressjs api. This is where I am having issues. When using google-auth-library to verify the token I am getting the error: "Error: Token used too late, number_1 > number_2". As far as I know the idToken has expired, but isn't it weird considering I sent it as soon as possible from the frontend. Backend code:
const { OAuth2Client } = require('google-auth-library')
require('dotenv').config()
const client = new OAuth2Client(process.env.CLIENT_ID)
const postGoogleLogin = async (req, res) => {
const { token } = req.body
try{
const ticket = await client.verifyIdToken({
idToken: token,
audience: process.env.CLIENT_ID
})
const { name, email, picture } = ticket.getPayload()
res.status(201).json({
name: name,
email: email,
picture: picture
})
}
catch(e){
console.log(e)
}
}
I have tried to verify the token using the endpoint https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 which says the token is valid, but as far as I know this endpoint should not be used in production
The issue appears to be from the library itself. As long as you're using the same client id on both React and ExpressJs, verifyIdToken should return a success response as long as the token is still valid.
Also, you can make use of https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123 in your production code.
Internally, the library call the same endpoint to verify your token.

Why am I getting a 431 status error when passing in a JWT token in Authorization section of the header?

So I am creating a full stack React app with Express and Node. I have implemented auth0 for authentication and authorization but I am getting the following error, does anyone have any suggestions on how to solve it? Thanks!
"Failed to load resource: the server responded with a status of 431 (Request Header Fields Too Large)"
The following is the class component where I am calling my api/tasks route and passing in the jwt access token from Auth0.
import React, { Component } from 'react';
import axios from "axios";
import {withAuth0} from "#auth0/auth0-react";
import config from "../auth_config.json";
const {apiOrigin = "http://localhost:3001"} = config
componentDidMount() {
const getProtectedTasks = async () => {
const {getAccessTokenSilently} = this.props.auth0;
const accessToken = await getAccessTokenSilently();
try {
const token = accessToken;
const self = this;
const response = await axios.get(`${apiOrigin}/api/tasks`, {
headers: {
Authorization: `Bearer ${token}`
}
})
self.setState({
allTasks: response.data
})
} catch {
}
}
getProtectedTasks()
}
The following is my code that handles the get api/tasks endpoint
const db = require("../models");
const jwt = require("express-jwt");
const jwksRsa = require("jwks-rsa");
module.exports = function (router) {
const authorizeAccessToken = jwt({
secret: jwksRsa.expressJwtSecret({
cache:true,
rateLimit:true,
jwksRequestsPerMinute:5,
jwksUri: `https://task-motivator.us.auth0.com/.well-known/jwks.json`
}),
audience: "https://quickstarts/api",
issuer: "https://task-motivator.us.auth0.com",
algorithms: ["RS256"]
});
router.get("/api/tasks", authorizeAccessToken, (req, res) => {
db.Task.findAll({}).then(data => {
res.json(data);
});
});

ExpressJS: Send Request Header Authentication

I have an API to authenticate the user with LDAP and I have been provided with the information which includes Content-Type: application/json and username and password for the request header and then the user's username and password to be passed in body. I tried the below code but it's not working. I want to know if I am passing the header request correctly or not.
router.post('/user', function(req, res){
var auth = {
content-type: "application/json",
username: "abcd",
password: "xyze"
}
auth.post('/user', {username: req.body.username, password: req.body.password"}, function(response) {
console.log(response);
})
})
Consider use axios package to make your requests: https://www.npmjs.com/package/axios
This link has a section “Creating an instance showing how you can set the header:
var instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
Once the header is set, invoke the post method, like this:
instance.post('/my/specific/endpoint/', myData);
In the following example, you can pass an authentication token as the header to your request:
import axios from 'axios';
const MY_BASE_URL = 'https://www.myserver.com/';
class MyLdapService {
static xhr(accessToken) {
const options = {
baseURL: MY_BASE_URL,
headers: {
Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
};
return axios.create(options);
}
static async myPostEndpoint(accessToken, data) {
return new Promise((resolve, reject) => {
this.xhr(accessToken).post('my-endpoint/', data)
.then(result => resolve(result.data.card))
.catch(err => reject(this.createError(err)));
});
}
}
So you can invoke the POST endpoint like this:
MyLdapService.myPostEndpoint('my_access_token', {});

Resources