SvelteKit redirect from hook.js - hook

After new version of svelteKit, you have to move your script type "module" to the file hook.js
But from this hook file i cannot redirect.
Do someone know about some solution please?

Worked for me
import { browser } from '$app/environment'
import { goto } from '$app/navigation'
export async function load({ url }) {
if (browser) {
const token = localStorage.getItem('token')
// check if user token exists
if (!token) {
goto('/login')
}
}
return url
}
Didn't work:
import { redirect } from '#sveltejs/kit ... redirect('/login')
return {status: 302, redirect: '/login'}

Related

How to check session in angular 8

I have created login form with angular 8 and node js. I have set the session using node js in back end. i couldnt check session set or not in angular for avoid access dashboard without logged in. Kindly suggest the way to use login system using angular 8 and node js. Thanks.....
A very popular method is to use JWT (JSON Web Tokens) npm package to authenticate.
The process would be:
Send credentials to the server
Server generates and sends back JWT or a Bearer Token
FrontEnd would store it in browser cookies or localStorage
localStorage.setItem('TOKEN', tokenReceivedFromServer);
In subsequent Api Calls the token would be sent to the server in a Header (Authorization).
Authorization: `JWT ${localStorage.getItem('TOKEN')}`
FYI: JWT keyword is removed from string on the server before parsing token
The frontend can check if the token is set in storage to show login page / dashboard
First we need to check the login credentials valid or not in application.
In angular application component typescript file, we have send the data service in argument, the service send the values to backend using httpclient. If credentials valid we set the value in localstorage.
submitLogin(data:any)
{
this.LoginService.loginData(data).subscribe(data =>{
if(data.body.status_code == 404)
{
Swal.fire({
icon: 'warning',
title: 'Invalid E-Mail/Password!',
}).then(function(){
});
}else if(data.body.status_code ==200)
{
localStorage.setItem("user_id",data.body.token);
this.router.navigate(['/Dashboard']);
}else
{
Swal.fire({
icon: 'error',
title: 'Process Failed!',
}).then(function(){
});
}
});
}
In service.ts file make sure about those packages import
import { HttpClient } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import {Login} from './login';
in loginData function
url = "http://localhost:3000/loginCheck";
loginData(Login:Login):Observable<any>
{
return this.http.post(this.url,Login,{observe: 'response'});
}
in backend i have used node.js
in file app.js
first install jsonwebtoken package and include in the file.
npm install jsonwebtoken
then set the jsonwebtoken when where condition satisfies
let payload = {subject:employee_id}
let token = jwt.sign(payload,'secretKey')
var response = {
'token': token,
"status_code":200,
}
res.send(response);
res.end();
Whenever we use the login in angular we must use the authguard routing its helps to access dashboard without logged in.
ng generate guard auth
in auth.guard.ts file we must include the package and service
import { CanActivate, Router } from '#angular/router';
import {LoginService} from './login.service';
export class AuthGuard implements CanActivate {
constructor(private LoginService:LoginService,private router:Router) {}
canActivate(): boolean
{
if(this.LoginService.loggedIn())
{
return true
}else
{
this.router.navigate(['/login']);
return false;
}
}
}
In this file we just checking the localstorage value set or not in boolean datatype.
in service file
add the following code for get and return in boolean type
loggedIn()
{
return !!localStorage.getItem('user_id')
}
getToken()
{
return localStorage.getItem('user_id')
}
if its returns true we can access the dasboard, else its redirected to login page.
We must use this canActive function in routing otherwise it will not working
In app-routing.module.ts file
import { AuthGuard } from './auth.guard';
const routes: Routes = [
{path:'Dashboard',component:DashboardComponent},
{path:'receipt',component:ReciptComponentComponent,canActivate:[AuthGuard]},
];
It will helpus to access dashboard without loggedin but we need to check the token valid or not in backend, we can do that using angular interceptors
we should create the new service with interceptors name
ng g service token-interceptor
In interceptor file we need to import the following
import { Injectable,Injector } from '#angular/core';
import { HttpInterceptor } from '#angular/common/http';
import { LoginService } from './login.service';
In interceptors services inject in different way compared to component.
export class TokenInterceptorService implements HttpInterceptor{
constructor(private Injector:Injector) { }
intercept(req:any,next:any)
{
let loginService = this.Injector.get(LoginService);
let tokenzedReq = req.clone({
setHeaders:
{
Authorization: `Bearer ${loginService.getToken()}`
}
});
return next.handle(tokenzedReq)
}
}
we need to create a function in interceptors with the name intercept, then we need to inject the service as per injector.
In backend we need to create the helper function to verify the jsonwebtoken
if the authorization not set we can send the response 401 not found and can redirected to login page
function verifyToken(req,res,next)
{
if(!req.headers.authorization)
{
return res.status(401).send('Unauthorized request');
}
var token = req.headers.authorization.split(' ')[1];
if(!token)
{
return res.status(401).send('Unauthorized request');
}
if(token === 'null')
{
return res.status(401).send('Unauthorized request');
}
//let payload = jwt.verify(token,'secretKey');
let payload = jwt.decode(token,'secretKey');
if(!payload)
{
return res.status(401).send('Unauthorized request');
}
req.userId = payload.subject;
next();
}
then we can use this middleware function wherever we need
for example
app.get('/dashboard',verifyToken,function(req,res){
let events = [];
res.json(events);
});
In dashboard component ts file
this.dashboardService.getData().subscribe(data=>this.dashboardData=data,
err=>{
if(err instanceof HttpErrorResponse)
{
if(err.status===401)
{
this.router.navigate(['/login']);
}
}
})
in dashboard service ts file
url = "http://localhost:3000/dashboard";
getData()
{
return this.http.get<any>(this.url);
}
in app.module.ts file
import { AuthGuard } from './auth.guard';
import { ReciptComponentComponent } from './recipt-component/recipt-component.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '#angular/common/http';
import { TokenInterceptorService } from './token-interceptor.service';
import { DashboardServiceService } from './dashboard-service.service';
in providers
providers: [AuthGuard,{provide:HTTP_INTERCEPTORS,useClass:TokenInterceptorService,multi:true},DashboardServiceService],

How to call an external URL from a react express node component?

I'm trying to create a login application that passes a JWT in the headers of another application.
I started from this application User authentication keycloak 2 adapted to my Kecloak installation and it works fine.
Now I need to create a component that call an external URL passing the authorization token
In this component
import React, { Component } from 'react';
class callUrl1 extends Component {
constructor(props) {
super(props);
this.state = { response: null };
}
authorizationHeader() {
if(!this.props.keycloak) return {};
return {
headers: {
"Authorization": "Bearer " + this.props.keycloak.token
}
};
}
handleClick = () => {
console.log("callUrl1 called")
}
}
export default callUrl1;
I need something that call an external URL; something like:
SOME_FUNCTION('https://www.h.net/users', this.authorizationHeader())
to put inside handleClick.
All that I tried gives compilation errors.
How can I go from "http://localhost:3000" to "https://www.h.net/users" passing the JWT?
The built in library for making requests in frontend JS is called Fetch. Here's an example of how you might do it in your case:
handleClick = () => {
fetch('https://www.h.net/users', this.authorizationHeader())
.then((response) => {
// do something with the response here...
});
}
or with async/await:
handleClick = async () => {
const response = await fetch('https://www.h.net/users', this.authorizationHeader());
// do something with response like:
const data = await response.json();
}
For more information on Fetch, check out mdn: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

How do I solve CORS issues in Apollo, Node, and Next.js?

I need help troubleshooting I CORS error I am having in Apollo, Node, and Next.js. I am not sure what change I have made, but suddenly I am unable to fetch the data from my Prisma database. I am currently running dev mode. My Yoga server which pulls in my data from Prisma run at localhost:4444. My frontend is run on localhost:7777.
Here is my CORS setup:
import withApollo from "next-with-apollo";
import ApolloClient from "apollo-boost";
import { endpoint, prodEndpoint } from "../config";
import { LOCAL_STATE_QUERY } from "../components/Cart";
function createClient({ headers }) {
return new ApolloClient({
uri: process.env.NODE_ENV === "development" ? endpoint : prodEndpoint,
request: (operation) => {
operation.setContext({
fetchOptions: {
credentials: "include",
},
headers,
});
},
// local data
clientState: {
resolvers: {
Mutation: {
toggleCart(_, variables, { cache }) {
// read the cartOpen value from the cache
const { cartOpen } = cache.readQuery({
query: LOCAL_STATE_QUERY,
});
// Write the cart State to the opposite
const data = {
data: { cartOpen: !cartOpen },
};
cache.writeData(data);
return data;
},
},
},
defaults: {
cartOpen: false,
},
},
});
}
export default withApollo(createClient);
variables.env
FRONTEND_URL="localhost:7777"
PRISMA_ENDPOINT="https://us1.prisma.sh/tim-smith-131869/vouch4vet_dev_backend/dev"
PRISMA_SECRET="..."
APP_SECRET="..."
STRIPE_SECRET="..."
PORT=4444
backend index.js
const server = createServer();
server.express.use(cookieParser());
// decode the JWT so we can get the user Id on each request
server.express.use((req, res, next) => {
const { token } = req.cookies;
if (token) {
const { userId } = jwt.verify(token, process.env.APP_SECRET);
// put the userId onto the req for future requests to access
req.userId = userId;
}
next();
});
I have tried rolling back to previous commit and I have had no luck. I have not ruled out internet problems.
Let me know if you need to see the rest of my repo.
Thanks

ReactJS+NodeJS: How to properly redirect user if not logged in?

I have a protected URL - this is how I redirect a user if he's trying to render a page he's not allowed to (this is in a ReactJS component):
render() {
if(!this.props.auth.isAuthenticated) {
this.props.history.push('/');
}
...
When he's not logged in, he's redirected on the homepage. But in the console, I get these 2 errors:
index.js:2178 Warning: Cannot update during an existing state transition (such as within `render` or another component's constructor). Render methods should be a pure function of props and state; constructor side-effects are an anti-pattern, but can be moved to `componentWillMount`.
The message suggests that I can move the if-block to componentWillMount? However, isn't componentWillMount deprecated?
and the 2nd error message:
xhr.js:178 GET http://localhost:3000/api/cars 401 (Unauthorized)
This message is caused by this block of code in a NodeJS route:
router.get('/cars', passport.authenticate('jwt'), function(req, res, next) {
if (req.isAuthenticated()) {
console.log('logged in');
Car.find({}).sort('name').exec(function(err, cars) {
if(err) throw err;
res.send(JSON.stringify(cars));
});
} else {
// not logged in
console.log('not logged in');
//res.send(401);
}
});
If the user is not authenticated, the 401 error is raised in the console and the code inside this route is not executed. Is this the correct behavior? Why there's still the error in the console?
EDIT: ReactJS component:
class Car extends Component {
constructor() {
super();
this.state = {
name: '',
errors: {},
cars: []
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
UNSAFE_componentWillMount() {
if(!this.props.auth.isAuthenticated) {
this.props.history.push('/');
}
}
componentDidMount() {
//console.log('x');
//console.log(this.props.auth);
//let self = this;
axios.get('/api/cars')
.then((response) => {
this.setState({cars: response.data});
}).catch(err => {
console.log('CAUGHT IT! -> ', err);
if (err.response.status === 401) {
//this.props.history.push('/');
}
return err;
})
}
componentWillReceiveProps(nextProps) {
if(nextProps.auth.isAuthenticated) {
this.props.history.push('/')
}
if(nextProps.errors) {
this.setState({
errors: nextProps.errors
});
}
}
handleInputChange(e) {
this.setState({
[e.target.name]: e.target.value
})
}
handleSubmit(e) {
e.preventDefault();
const car = {
name: this.state.name
}
console.log(car);
axios.post('/api/cars/create', car)
.then(function(response) {
console.log('response.data: ', response.data);
if(response.data == "success"){
console.log('successssss');
}
}).catch(function(err) {
console.log(err)
});
}
render() { ...
Please refrain from asking multiple question in one stack overflow question
Error 1:
The error message clearly states that you should not navigate to another page in the render method. But you are doing just that. As the message suggest you could move the code in the componentWillMount livecycle method, but note that this the check will not run on every re-render then.
Error 2:
You seem to be calling this route, which is protected by authentication, while being un-authenticated. Without seeing your client side code I cannot comment further.
Patrick explained about the errors above.
componentWillMount lifecycle method. is not deprecated as far i know.
I am guessing you are using React Router for your routing needs.
A good example of how to do it properly is react router private route example
It uses Route and Redirect from react-router-dom and creates one special PrivateRoute component. For every route that requires authentication and redirects unauthorised users you’d use this PrivateRoute component instead of just Route component.
you can check authentication and render something else inside the render lifecycle method if needed. But you should not redirect from inside render method.
You can redirect the user like this:
import {Redirect} from 'react-router-dom';
...//inside constructor
this.state={
redirect_path:''//redirect_path is the path you want to redirect the user to
}
In componentDidMount check if the user is authorized or not,
If not:
this.setState({
redirect_path:'path_to_redirect_to'
})
In render method:
render()
{ //push will add it to the browser history
if(this.state.redir)
{
return(
<Redirect push to={this.state.redirect_path} />
}
else
{
//return the page
}
}

How to implement auto refresh token in graphql for jwt based authentication?

I am trying to figure out this scenario for my JWT based authentication in Apollo based graphql server (2.0) .
Basically after login a user gets accessToken and refreshToken from server.
AccessToken gets expired after certain period of time and server sends an error message indicating that token expired (TokenExpiredError) and then client need to communicate with server for new accessToken via passing refreshToken.
Flow is as following -
TokenExpiredError occurs
Get that error on client side
Queue all requests with old accessToken(so that server is not flooded with too many refreshToken calls and many accessTokens are generated by server)
Call refreshToken api on graphql server to get new accessToken
update accessToken for all authorised calls with new accessToken
Logout user incase refreshToken itself is expired
Prevent any kind of race condition b/w calls
I have already implemented refreshToken mutation on client side but can't figure out about when error occurs stop all requests -> request new token -> make all pending request again and if refresh token is expired logout user.
I followed this approach to solve my problem finally
Posting my approach for others
// #flow
import { ApolloLink, Observable } from 'apollo-link';
import type { ApolloClient } from 'apollo-client';
import type { Operation, NextLink } from 'apollo-link';
import { refreshToken2, getToken } from './token-service';
import { GraphQLError } from 'graphql';
export class AuthLink extends ApolloLink {
tokenRefreshingPromise: Promise<boolean> | null;
injectClient = (client: ApolloClient): void => {
this.client = client;
};
refreshToken = (): Promise<boolean> => {
//if (!this.tokenRefreshingPromise) this.tokenRefreshingPromise = refreshToken(this.client);
if (!this.tokenRefreshingPromise) this.tokenRefreshingPromise = refreshToken2();
return this.tokenRefreshingPromise;
};
setTokenHeader = (operation: Operation): void => {
const token = getToken();
if (token) operation.setContext({ headers: { authorization: `Bearer ${token}` } });
};
request(operation: Operation, forward: NextLink) {
// set token in header
this.setTokenHeader(operation);
// try refreshing token once if it has expired
return new Observable(observer => {
let subscription, innerSubscription, inner2Subscription;
try {
subscription = forward(operation).subscribe({
next: result => {
if (result.errors) {
console.log("---->", JSON.stringify(result.errors))
for (let err of result.errors) {
switch (err.extensions.code) {
case 'E140':
console.log('E140', result)
observer.error(result.errors)
break;
case 'G130':
this.refreshToken().then(response => {
if (response.data && !response.errors) {
this.setTokenHeader(operation);
innerSubscription = forward(operation).subscribe(observer);
} else {
console.log("After refresh token", JSON.stringify(response));
observer.next(response)
}
}).catch(console.log);
break;
}
}
}
observer.next(result)
},
complete: observer.complete.bind(observer),
error: netowrkError => {
observer.error(netowrkError);
}
},
});
} catch (e) {
observer.error(e);
}
return () => {
if (subscription) subscription.unsubscribe();
if (innerSubscription) innerSubscription.unsubscribe();
if (inner2Subscription) inner2Subscription.unsubscribe();
};
});
}
}

Resources