NuxtJS - Middleware get and set cookies - vue.js

does anyone have experience on redirecting a user based on the cookies? so basically I need to check before someone enters my app if he has access to it otherwise to redirect him somewhere else.
I am trying to apply my logic into a middleware but I am getting an error each time I try to set cookies (after doing a fetch/axios call): ERROR Cannot set headers after they are sent to the client
for setting the cookies I am using the cookies-universal-nuxt plugin
export default function (context) {
let payload = {
cookie1: context.$cookies.get("cookieName1"),
cookie2: context.$cookies.get("cookieName2"),
}
let cookie1= '';
let cookie2= '';
context.store.dispatch('checknCookies', payload)
.then(() => {
cookie1= context.store.getters.getCookie1;
cookie2= context.store.getters.getCookie2;
context.$cookies.set('cookieName1', cookie1, {
path: '/',
maxAge: 10,
expires: 0,
// domain: 'localhost'
})
context.$cookies.set('cookieName2', cookie2, {
path: '/',
maxAge: 10,
expires: 0,
// domain: 'localhost'
})
})
})
When I try to set the cookies before calling the store (where I do an axios call to retrieve the names of the cookies) they are set fine. after the axios call then I get the above error.
I haven't found anything that it can help me and I looked at almost all the questions in here which are similar to this.

Related

PassportJS OAuth2Strategy: authenticate returns 400 instead of redirecting

I'm trying to setup discord oauth2 pkce using passportjs and the passport-oauth2
const discordStrategy = new OAuth2Strategy({
authorizationURL: 'https://discord.com/api/oauth2/authorize',
tokenURL: 'https://discord.com/api/oauth2/token',
clientID: DISCORD_CLIENT_ID,
clientSecret: DISCORD_CLIENT_SECRET,
callbackURL: DISCORD_CALLBACK_URL,
state: true,
pkce: true,
scope: ['identity', 'scope'],
passReqToCallback: true,
},
(req: Request, accessToken: string, refreshToken: string, profile: DiscordUserProfile, cb: any) => {
prisma.user.findUnique({ where: { email: profile.email ?? '' }}).then(foundUser => {
if (foundUser === null) {
// Create a new user with oauth identity.
} else {
cb(null, foundUser)
}
}).catch(error => {
cb(error, null);
})
});
I've been following the google example as well as some others, these examples indicate that, I should be able to use:
passport.use('discord', discordStrategy);
and
authRouter.get('/discord', passport.authenticate('discord'));
and this should redirect to the OAuth2 providers login page, but instead, I get a 400 Bad Request "The request cannot be fulfilled due to bad syntax." The response body contains an object:
{"scope": ["0"]}
Why is this happening instead of the expected redirect?
My intention is that, once the user logs in, I should get a code, then I can post that code and the code verifier to get an access token, then once the access token is obtained, the actual authenticate call can be made
Edit: I put breakpoints in the passport.authenticate function and I stepped through it. It does actually get through everything and it calls the redirect. The parsed URL it generates, even if I copy it and manually navigate to the URL, it gives me the same, just gives:
{"scope": ["0"]}
and no login page, why?
If you add a version number to the base api url, e.g. /v9 it gives a full error message.
It turned out I had typo'd the scopes, I had 'identity' instead of 'identify' - now this part of the process is working as expected.

ExpressJS apply JWT for file url

So I'm trying to make authorization for routes with JWT, it all worked if used on routes.
app.get('/user/list', jwtMiddleware, action);
And the jwtMiddleware content is (more or less):
var token = req.headers.authorization;
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, process.env.SECRET_TOKEN, function(err, decoded) {
if (err) {
return res.status(401).send({
success: false,
message: 'Sign in to continue.'
});
} else {
// if everything is good, save to request for use in other routes
next();
}
});
} else {
// if there is no token
// return an error
return res.status(401).send({
success: false,
message: 'Sign in to continue.'
});
}
it works, but I have these image files in uploads/ folder which accessible by /upload/image-1.jpg and I want to prevent direct access to /upload/image-1.jpg by using wildcard routes app.get('/upload*', jwtMiddleware, action);
then I try accessing random route with upload prefix like /upload/test, the jwt middleware works. But if I explicitly type /upload/image-1.jpg the browser just show the image, it's like the middleware or wildcard route (/upload*) is not accessed (the console.log inside middleware didn't even fired).
Previously I use restify and restify-jwt-middleware, it could handle this case flawlessly but in express I can't find out why it doesn't work. Maybe because restify-jwt-middleware automatically registers all routes into jwt validation whereas express need to declare each route with jwt middleware manually.
is there anything I miss in this case? thank you.
add/modify to another route like app.get('/upload/:image', jwtMiddleware, action)
this will check all the route you mentioned /upload/*
EDIT :
put the static files(eg.uploaded files somewhere like images/upload) and route them using the serveStaticFiles plugin restify and put jwt middleware to verify the user login status.
server.get(
'/uploads/*',
jwtMiddleware,
restify.plugins.serveStaticFiles('./images/upload')
);
In case anyone still confused, here's my answer in express which is similar approach to yathomasi's
// the fake route
app.get('uploads/:name', jwtMiddleware, (req, res, next) => {
if (fs.existsSync('./realpath/' + req.params.name)) {
res.sendFile('./realpath/' + req.params.name);
} else {
res.status(404).body({status : 'ERROR', message : 'File not found'});
}
});
this way, the uploads/somefile.jpg is treated as route url not file url and will be processed by jwtMiddleware

auth0-js: UnauthorizedError: No authorization token was found, though logged in

I created an app with Vue (including Vue-Router), Node and Express.
I'm trying to secure my App with SSO, using auth0-js.
I created an Auth0-Account and followed this tutorial.
My Login function looks as follows:
import auth0 from 'auth0-js'
var auth = new auth0.WebAuth({
clientID: <my-client-id>,
domain: '<my-auth0-domain>/'
})
export function ssoLogin () {
auth.authorize({
responseType: 'token id_token'
redirectUri: http://localhost:8000/callback,
audience: 'https://<my-auth0-domain>/userinfo',
scope: 'full_access'
})
}
While the login itself works fine, I can't seem to find out how to secure the secret routes of my app.
Following the above mentioned tutorial, I used express-jwt and jwks-rsa, like this:
var jwt = require('express-jwt')
var jwks = require('jwks-rsa')
var authCheck = jwt({
secret: jwks.expressJwtSecret({
cache: true,
rateLimit: true,
jwksRequestsPerMinute: 5,
jwksUri: "https://<my-auth0-domain>/.well-known/jwks.json"
}),
audience: <my-client-id>,
issuer: "https://<my-auth0-domain>/",
algorithms: ['RS256']
})
app.post('/send-sensitive-data', authCheck, function (req, res) {
// this post requests sends some data, and should only do so, if a user is logged in
})
However, even if I'm logged in via SSO, when I try to access the sensitive data, I obtain
UnauthorizedError: No authorization token was found
I have no idea where I went wrong. This seems like a very stupid question, but: Can somebody tell me, where the authorization token must be, so it will be found?
I would really appreciate if someone helped me by this or gave me a hint.
Please feel free to ask for more code snippets, if that might help.
Okay, I found the answer on my own ... but in case anyone is making the same mistake as I'm doing: I forgot to set the header in the axios.post request, like that:
axios({
method: 'post',
url: '/send-sensitive-data',
data: somedata,
headers: {
Authorization: 'Bearer ' + getAccessToken()
}
})
.then(response => {
// do something with the response
})

Supertest request with CSRF fails

I have an Express 4 application that makes user of csurf for CSRF protection on API routes. The application is working perfectly and CSRF protection is indeed working where requests without the csrf-token header will give the appropriate error.
I make use of Ava for testing with supertest for testing routes. The following test fails when CSRF checking is enabled but passes if I remove the middleware:
test('booking api no auth', async t => {
t.plan(4)
const server = await request(makeServer(t.context.config, t.context.connection))
const csrf = await server
.get('/')
.then(res => new JSDOM(res.text))
.then(dom => dom.window.document.querySelector('meta[name="csrf_token"]'))
.then(csrfMeta => csrfMeta.getAttribute('content'))
const GET = await server
.get('/v2/Booking')
.set('csrf-token', csrf)
const POST = await server
.post('/v2/Booking')
.set('csrf-token', csrf)
.send({
name: 'Test',
description: 'Test',
category: 'diving',
minimumPax: 1,
maximumPax: 2,
priceAdult: 1,
priceChild: 1
})
const res = { GET, POST }
t.is(res.GET.status, 403)
t.deepEqual(res.GET.body, text['403'])
t.is(res.POST.status, 201)
t.truthy(res.POST.body._id)
})
I have verified that the header is indeed set in the request. Any ideas or suggestions for alternative libraries that works is appreciated.
I've previously also had errors with supertest and logging in, still unresolved, but using supertest-session seems to have fixed this for me. Fix was to replace:
import request from 'supertest'
with
import request from 'supertest-session'
and everything magically works.

Angular 2 AuthHttp with jwt not connecting

I'm trying to use jwt's authHttp to set an API connection to a particular Back End. I'm trying to make it first without any token so I can test it but it seams like it's not even getting connected. I'm using it as following:
this.authHttp.get('localhost:3001/api/basic')
.subscribe(
data => console.log("data"),
err => console.log(err),
() => console.log('Request Complete')
);
The error I'm getting in the console is AuthHttpError {}
I've set my ngModules as it say in the guide:
providers: [
{
provide: AuthHttp,
useFactory: authHttpServiceFactory,
deps: [Http, RequestOptions]
}
And
function authHttpServiceFactory(http: Http, options: RequestOptions) {
return new AuthHttp(new AuthConfig({noTokenScheme : true}), http);
}
The thing that drive's me crazy is that using http it works fine like this:
this.http.get('http://localhost:3001/api/basic').subscribe(
data=> console.log(data),
error=> console.log("Getting Error")
);
You are probably thinking "Why he is not using http then instead of authHttp?". Well, that's because setting a heather "Authorization" and its token seams impossible with http.
Any help or guidance would be extremely helpful.
If you don't need JsonWebTokens but simply want to add custom headers, you can do it this way without having to import the angular2-jwt library :
In your service :
private customHeaders: Headers = this.setCredentialsHeader();
setCredentialsHeader() {
let headers = new Headers();
let credentials = window.localStorage.getItem('credentials2');
headers.append('Authorization', 'Basic ' + credentials);
return headers;
}
someMethod() {
let url = 'your.URL.to.API';
return this.http
.get(url, { headers: this.customHeaders })
.map(result => {
console.log(result);
});
}
This way you can add your Authorization header with the type of data you want.
If it's a Authorization Bearer type header you are looking for and use it with angular2-jwt, you can use the default configuration first before trying to provide your own AuthHttp instance through the factory. It will be much simpler to debug and figure where the problem is.
From the documentation : https://github.com/auth0/angular2-jwt#configuration-options
AUTH_PROVIDERS gives a default configuration setup:
In your module with your service, just import the AUTH_PROVIDERS like this :
import { AUTH_PROVIDERS } from 'angular2-jwt';
...
#NgModule({
...
providers: [
AUTH_PROVIDERS,
...
]
})
and simply use the AuthHttp instance in your service like you did.
You should see in the Navigator Network tab your headers being added to your request.
EDIT :
As stated in the documentation, it is appending the token value in the headers from the Token Getter Function defined in the AUTH_PROVIDERS by default.
You therefore need to add your JWT in your LocalStorage with the default name id_token.
To give you my working example, I'm setting a JWT upon the authentication process, where I get a JWT as a response from my Http Call :
auth.service.ts
this.identityService.setToken(token.accessToken);
identity.service.ts
setToken(token?) {
if (token) {
window.localStorage.setItem('id_token', token);
} else {
window.localStorage.removeItem('id_token');
}
}
You should be able to see your JWT in your network tab if done correctly.
Afterwards, the AuthHttp instance should add the headers to your requests as intended...
It might not work correctly if your Token is not a JWT. To check if it's a good one, you can use a website such as https://jwt.io/ where it will be decoded.
If it's still not working, this means the problem is coming from elsewhere. A service not provided correctly, etc.