I have logged into parse from cloud code using Parse.User.logIn
After a successful login have retrieved session token using user._session
Parse.User.logIn(request.params.userdata.email, "sdfisadufhkasdjhf", {
success: function(user) {
response.success(user._sessionToken);
},
error: function(user, error) {
}
});
This session token is passed to the client which then makes a REST API call by setting the token in the header.
However, the rest API call is not successful and returns invalid session token error.
REST API call works perfect when I don't send session token for requests that don't need authentication
From chrome console, I can see that the headers are set correctly and the value of session token is same as Parse.User.current().getSessionToken()
in app.config()
$httpProvider.defaults.headers.post['X-Parse-Application-Id'] = "dxfhgfxhxhxhxxxxxxxxxxxxxxxxxxxxxdgerstrattgrft";
$httpProvider.defaults.headers.post['X-Parse-REST-API-Key'] = "gfhjjhfjfjjchfjcccccccccccccccccccccccccccccccccccc";
$httpProvider.defaults.headers.post['Content-Type'] = "application/json";
From controller
$scope.createGroup = function()
{
shan = $scope.creategroup;
$http.post('https://api.parse.com/1/functions/addGroup', $scope.creategroup,
{ headers: {
'X-Parse-Session-Token':sessionToken
}
}).success(function(data, status, headers, config) {
alert("success : "+JSON.stringify(data));
}).
error(function(data, status, headers, config) {
alert("error : "+JSON.stringify(data));
});
}
Related
I am trying to create a post request for refreshing the token using axios.post
my code is the following
I can't seem to pass the parameters in the correct order/way
in the api request its like this
export async function refreshTheCurrentToken() {
const url = RefreshCurrentToken;
const refreshTokenHardCoded = "xxxxxx"
const refreshedToken = await axios
.post(url, {
params: {
string: refreshTokenHardCoded,
},
})
.catch((error) =>
console.log(error + " 🟥error refreshing the current token")
);
// console.log(url + " URL FOR REFRESHING TOKEN");
console.log(refreshedToken + " NEW TOKEN GENERATED ✅");
// return refreshToken;
}
my response is the following
LOG AxiosError: Request failed with status code 400 🟥error refreshing the current token
LOG undefined NEW TOKEN GENERATED ✅
tried setting the refresh token in a static way. on postman it works but on my react native project it doesn't.
tried converting the refresh token a string, tried creating an object to hold the refresh token
I am in a next-js app and my auth token is stored in cookies.
For some raisons i use Swr and Api route to fetch my secured api backend.
i am trying to find a way to put my auth token in all api request.
During login cookie is set
res.setHeader(
'Set-Cookie',
cookie.serialize('token', data.access_token, {
httpOnly: true,
secure: process.env.NODE_ENV !== 'development',
maxAge: data.expires_in, // 1 week
sameSite: 'strict',
path: '/',
}),
);
This is an example of a page using swr fetch
//page/test.ts - example of my test route
const { data, error } = useFetchContent(id);
if (error) {
showError('error');
replace('/');
}
return <DisplayContent content={data} />
This is a swrFetchHook
// fetchContentHook
function useFetchContent(id: string): ContentDetail {
return useSWR<any>(`/api/content/${id}`, fetcherApiRoute);
}
const fetcherApiRoute = (url: string): Promise<any> => {
return axios(url)
.then((r) => r.data)
.catch((err) => {
console.info('error is ', err)
throw err
});
};
export default useFetchContent;
inside api route
export default async (req, res): Promise<ContentDetail> => {
const { id } = req.query;
if (req.method === 'GET') {
const fetchRealApi = await apiAxios(url);
if(fetchRealApi) {
// here depending on result of fetchRealApi i add some other fetch ...
return res.status(200).json({ ...fetchRealApi, complement: comp1 });
}
return res.status(500)
}
return res.status(500).json({ message: 'Unsupported method only GET is allowed' });
};
and finally api axios configuration
const apiAxios = axios.create({
baseURL: '/myBase',
});
apiAxios.interceptors.request.use(
async (req) => {
// HERE i am trying to get token from cookies
// and also HERE if token is expired i am trying to refresh token
config.headers.Authorization = token;
req.headers['Content-type'] = 'application/x-www-form-urlencoded';
return req;
},
(error) => {
return Promise.reject(error);
},
);
export default apiAxios;
I am stuck here because i cant find token during apiAxios.interceptors.request.use...
Did you know what i am doing wrong, and am i on a correct way to handle this behavior ?
To allow sending server cookie to every subsequent request, you need to set withCredentials to true. here is the code.
const apiAxios = axios.create({
baseURL: '/myBase',
withCredentials: true,
});
Nilesh's answer is right if your API is able to authorize requests based on cookies. Also it needs the API to be in the same domain as your frontend app. If you need to send tokens to the API (the one which is in the cookie), then you will need a small backend component often called BFF or Token Handler. It can extract the token from the cookie and put in an Authorization header.
At Curity we've created a sample implementation of such a Token Handler, of which you can inspire: https://github.com/curityio/kong-bff-plugin/ You can also have a look at an overview article of the Token Handler pattern.
How to configure flask app with flask-jwt-extended for which we need something like below.
AccessToken/Bearer must sent as a Header (and not cookie)
RefreshToken must sent as httpOnlyCookie for /api/refreshtoken path only
How to set two different token one in header and one in cookie? We are able to set either both as cookie or both as a header.
Any help?
Thanks
Raxit
I wanted to do the same while building a React + Flask single page application after days of headache trying to understand authorization and authentication as I am a beginner.
Anyways, I managed to do it this way:
In Flask, config:
app.config['JWT_TOKEN_LOCATION'] = ['headers', 'cookies']
app.config['JWT_REFRESH_COOKIE_PATH'] = '/auth/refresh'
And what I return in my login function:
resp = jsonify({'access_token': access_token})
set_refresh_cookies(resp, refresh_token)
return resp, 200
And in my refresh function:
# Refresh access token
#app.route('/auth/refresh', methods=['POST'])
#jwt_refresh_token_required
def refresh():
user = get_jwt_identity()
resp = {
'access_token': create_access_token(
identity={
'username': user['username'],
'role': user['role']
},
expires_delta=timedelta(seconds=600),
user_claims=user['role']
)
}
return jsonify(resp), 200
And on the front side, I collect the JSON access_token and set it in memory and use withCredentials to send the refresh_token with my API calls.
axios.defaults.withCredentials = true;
axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
more precisely:
.then(({ data: { access_token } }) => {
axiosHttp.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
return jwt_decode(access_token);
})
then I use the data from my decoded access_token in a React Context Component to authenticate access to pages depending on roles.
logout is simply setting to null my context and calling the api to unset the refresh cookie
#app.route('/auth/logout', methods=['DELETE'])
#jwt_required
def logout():
resp = jsonify({"msg": "Successfully logged out"})
unset_jwt_cookies(resp)
return resp, 200
it's quite simple in the end but it took me quite a while to figure out!
I'm building a web application using the MERN stack. I've made a REST API to interact with my front-end the usual way,but I'm not able to figure out the best way to build a secure API and overall security of the application.
So far this is what I've tried
Flow of authenticating a user/request :
1. User enters the credentials
2. Server responds with access_token and refresh_token, caching refresh_token in redis cache with email as key and access_token in localStorage
3. To access a protected route, user sends the request with Bearer {ACCESS_TOKEN} in request header
4. Server checks if the token is valid and not expired, serving the user back with protected resource
5. In case, the access_token is expired (i've kept the token expiry short eg. 5 min), an action is fired from the front-end (using redux actions), a sample request :
POST http://localhost:3000/user/token
Header Bearer {ACCESS_TOKEN}
Body
{
"email" : "user#example.com"
}
Server performs a check in redis cache if the email has refresh_token
If yes, server responds with updated access_token
This is how I'm signing the tokens
const signToken = user => {
let email = user.email;
let name = user.name;
const accessToken = JWT.sign({
iss : process.env.APP_NAME,
sub : user.id,
email : email,
name : name
}, JWT_SECRET, {
expiresIn : 300
});
const refreshToken = JWT.sign({
iss : process.env.APP_NAME,
sub : user.id,
email : email,
name : name
}, REFRESH_TOKEN_SECRET, {
expiresIn : '30d'
});
// Save to redis cache
REDIS_CLIENT.set(email, refreshToken);
return {accessToken, refreshToken};
}
and for getting new access_token
// Refresh token
const refreshToken = (req, res, next) => {
const extractToken = req.headers['authorization'];
const token = extractToken.split(' ')[1];
if (!token) {
return res.status(403).json({
message : 'Unauthorized'
});
}
REDIS_CLIENT.get(req.body.email, (err, cachedToken) => {
if (err) return res.status(500).json({message : 'Something went wrong'});
if (cachedToken == null) {
return res.status(403).json({message : 'Unauthroized'});
} else {
JWT.verify(cachedToken, REFRESH_TOKEN_SECRET, (err, rt) => {
if (err) {
return res.status(500).json({message : 'Something went wrong'})
} else {
// Generate a new access token here
const newAccessToken = JWT.sign({
iss : process.env.APP_NAME,
sub : rt.sub,
email : rt.email,
name : rt.name
}, JWT_SECRET, {
expiresIn : 300
});
return res.json({
"accessToken" : newAccessToken
});
}
});
}
});
}
Is this approach secure? If not, what are some good ways to design the authentication flow if stack is MERN. Upon searching the internet, many have advised to set short expiry in access_token and use the refresh_token to generate new access_token, but I haven't found how to logout user on inactivity? What if attacker gets the expired token and email id, and generates the new access_token? How will be the oAuth integration?
PS : Sorry for putting so much here, came here after a lot of searches on the internet but found nothing much
I'm using Grails version 2.4.3 . I am creating an application that supports RESTful APIs. Since access to these APIs should be authenticated , I tried out the Spring Security REST plugin. I checked out this example and what I could understand is , the /api/login controller is the authentication point which receives the user credentials in JSON format and after successful authentication it provides the acces token as response. I tried sending a POST request to /api/login/ with valid JSON data using the POSTMAN Rest Client. But it gives me the following error.
401 Unauthorized , Similar to 403 Forbidden, but specifically for use when authentication is possible but has failed or not yet been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the requested resource.
I also tried using IntellijIDEA's REST Client but doesn't work.
Then i tried by sending AJAX Request to /api/login/ with valid JSON data
, but getting 401 on console. What is the problem here? Is this the correct login end point? How can i get authenticated using JQuery?
Try this
$.ajax({
url: " http://localhost:8080/AppName/api/login",
type: "POST",
crossDomain: true,
data: JSON.stringify({"username":"yourusername" , "password":"yourpassword"}),
contentType: 'application/json; charset=utf-8',
dataType: "json",
success: function (response) {
console.log(response);
},
error: function (xhr, status) {
alert("error");
}
}) });
You can try this code for authentication,I am sending user id and password in request header you can try as you wish :-
inject following services:-
def springSecurityService
def authenticationManager
and use following code
def login = {
final String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.startsWith("Basic")) {
boolean authResult = authenticateUser(authorization)
if (authResult) {
render response.status
} else {
render authFailed(response)
}
} else {
render authFailed(response)
}
}
protected boolean authenticateUser(String authorization) {
// Authorization: Basic base64credentials
def base64Credentials = authorization.substring("Basic".length()).trim();
byte[] credentials = base64Credentials.decodeBase64()
String actualCredential = new String(credentials)
// credentials format like username:password
final String[] values = actualCredential.split(":", 2);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(values[0], values[1]);
try {
def authentication = authenticationManager.authenticate(authRequest);
def securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
def session = request.session;
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
}
catch (BadCredentialsException exception) {
return false
}
return true
}
protected HttpServletResponse authFailedResponse(HttpServletResponse response) {
response.setStatus(401)
response.setHeader("WWW-Authenticate", "Basic realm=\"nmrs_m7VKmomQ2YM3:\"")
return response;
}