adding jwt authguard throws unauthorized error - jwt

I have written the following login module with the nesjts 'typeorm'.
#Post('login')
public async login(#Body() data) {
return await this.authService.login( data);
}
It works fine and send me the desired result (contains the jwt token).
But when I add #UseGuards(AuthGuard('jwt')) at the top of this service, I get the error 401, unauthorized access.
I don't understand why it gives this error, because when I login I will protect it.

When you login, the request doesn't have the jwt token in the header.
The login method shouldn't be protected by the guard.

Related

How do I fix an "Unable to parse JWT" error on Identity Aware Proxy?

I am trying to use a cloud run endpoint through GCP's Identity Aware Proxy and all of a sudden the IAP endpoint started throwing an error:
Invalid IAP credentials: Unable to parse JWT
I am using the extension_google_sign_in_as_googleapis_auth extension to create a Google client out of my existing Google/Firebase login.
The IAP works fine if I access the api with the browser directly (using the same GCP credentials directly as I am logged into the app with)
I am using the following code, which seems to be connecting to the backend: I see the network inspector fire the CORS head and then the call to the endpoint. The first is fine, the second errors with a 401 and the message above in the body.
getIAPAPI(String path) async {
Uri uri;
// make sure the Identity Aware Proxy is addressed authenticated
var _signIn = GoogleSignIn(
scopes: <String>[CloudIAPApi.cloudPlatformScope],
);
await _signIn.signInSilently();
// create a GCP client
final _client = await _signIn.authenticatedClient();
print('fetching ${path} from api');
try {
uri = Uri.https('iapapi.example.com', path);
var response = await _client?.get(uri);
return response?.body;
} catch (e) {
// print errors and pass back an empty json result
print(e);
return "{}";
}
}
Am I doing something wrong in my code? The really weird thing is that it seemed to work a week ago. I don't see anything in the IAP console settings that could help either.

How do I call my Cognito secured RestAPI from the browser when using next-auth?

I have an AWS RestApi secured by AWS Cognito. In addition to this I have a NextJS app using next-auth that provides user authentication against the Cognito User Pool.
I now want to call the RestApi directly from the browser, but cannot find a way to include the proper credentials. Since the only cookies present in my web-app begin with next-auth- I assume they are not suitable for the task.
So, how do I access the access token from the browser?
I ended up hooking up to two callbacks on the NextAuth configuration, like this:
NextAuth({
providers: [
CognitoProvider({
idToken: true,
issuer,
clientSecret,
clientId,
authorization,
}),
],
callbacks: {
session: async function ({ session, token }) {
return {
...session,
bearerToken: token.bearerToken ?? session.bearerToken,
};
},
async jwt({ token, account }) {
token.bearerToken = account?.id_token ?? token.bearerToken;
return token;
},
},
})
From the pages/api/auth/[...nextauth].ts file.
This makes the bearerToken available via the getSession call:
import { getSession } from "next-auth/react";
// ...
const { bearerToken } = await getSession();
You can use application like Postman to pass the Authorization header. I am not sure if your query is about getting the access token or about how to use the access token.
In order to get the access token and then to call your REST API, you need to have a server. Suppose you have your server with domain name "example.com". Then, put this server name in the callback URL of your Cognito user pool's app client.
After user authentication, Cognito will send the access token to "example.com". Then, you server will have the responsibility to correctly call the REST API with the access or ID token provided by Cognito.
For testing purpose, you can manually get the access token after authenticating with Cognito. Then, you can use application like Postman to make HTTP calls to your REST API endpoint with the access token. Put the token as value to the authorization header.

Securing a restful API verifying clients with JWT

I have a RESTful API using JWT for authentication purposes. The first call I receive from a client is the /login call, with the following payload (no headers)
{
"username" : xxxx,
"password": wwww
}
The server verifies if the user is registered and then returns a signed JWT to the client in order to be received in the next calls.
I wonder if this is secure enough. I don't check anywhere if the client sends me a client id / client secret (like in OAuth) so I cannot verify if this call is from my webapp / apps or if it is an external client which I don't know about. I want to know if it makes sense to implement this behavior using JWT and how to implement it.
(I know how to do it with OAuth2 but I don't want to move now from JWT authentication)
Thank you!
If I understood you correctly, you should create a function somewhat similar to this:
function verify(req, res, next) {
const token = req.header('x-auth-token');
if (!token) {
return res.status(401).json({
msg: 'No token, auth denied'
});
}
try {
const decoded = jwt.verify(token, config.get(YOUR_SECRET_GOES_HERE));
req.user = decoded.user;
next();
} catch (err) {
res.status(401).json({
msg: 'Token is not valid'
});
}
}
For all secured API endpoints you should apply it like this:
router.get('/anyuserinfo', verify, (req, res) => ...
And that is it. The function will send 401 response if no token is provided.
I think I found another Stackoverflow question that answers mine:
JWT (Json Web Token) Audience "aud" versus Client_Id - What's the difference?
In a nutshell, client_id and client_secret should be sent on headers to the server to be validated before sending a new JWT token.

Error 401 (Unauthorized) When making REST calls using Axios with JWT headers included

I'm developing a small react node application with JWT passport for authentication. I've tested all the endpoint through postman(by passing token with authorization header) and they are working properly.
This is the call im making from the front-end
export const getUsersDetails=()=>{
console.log( localStorage.getItem('jwtToken'));
return (dispatch) => {
return axios.get('http://localhost:3030/users',
{ headers: { 'Authorization': localStorage.getItem('jwtToken') } }
).then((data)=>{
console.log('data comming',data);
dispatch(getUsersData(data));
}).catch((error)=>{
console.log('error comming',error);
dispatch(errorgetUsersData(error));
});
};
}
I have enable CORS by using the the CORS module. this is the how the network calls looks like from the browser
the authorization header looks like
authorization:[object Object], eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.....
Should this be like authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.....
Is this the reason why im facing this issue? How to overcome this?
I was able to solve a similar issue on a MERN stack, by configuring axios globally in the react application, by adding Bearer and one space, in front of the token that is assigned globally.
axios.defaults.headers.common['Authorization'] =Bearer ${token};
initially, it was without Bearer and i kept getting a 401 status code.
axios.defaults.headers.common['Authorization'] = token;
When you want authorization in your app, it depends on how you have done your back end. If everything is ok trough postman, show how your headers in postman look when you have tasted. I use xsrf token and here is how my request header look:
{headers:
{"Access-Control-Allow-Headers" : "*",
"X-XSRF-TOKEN": this.$cookie.get('XSRF-TOKEN')}
}
Maybe you should just put "Access-Control-Allow-Headers" : "*"

Soundcloud API error 401 when i use a token later than just after i get it

I would like to understand why i get "The requested URL responded with HTTP code 401." when i try to put a description whith an access token.
The weird think is it works fine when i do that just after getting the access_token (session) from the user, but when i store the token, and try to launch the same code later, it fail !
Apparantly, there is a problem with the token, because i can access the soundcloud description without token, but if i use this method: $soundcloud->setAccessToken($token); before getting the tracks datas, i can't access them anymore...
Here is the code:
require_once 'soundcloud/Soundcloud.php';
$soundcloud = new Services_Soundcloud(SOUNDCLOUD_CLIENT_ID, SOUNDCLOUD_CLIENT_SECRET, SOUNDCLOUD_REDIRECT_URI);
$soundcloud->setAccessToken($session_token);
try
{
$track = json_decode($soundcloud->get('tracks/'.$media_id), true);
}
catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e)
{
exit($e->getMessage());
}
try
{
$response = json_decode($soundcloud->put(
'tracks/'.$media_id,
'test',
array(CURLOPT_HTTPHEADER => array('Content-Type: application/xml'))), true);
}
catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e)
{
exit($e->getMessage());
}
This code works when i just get the token but fail if i launch it a few days later...
Thanks for help !
Where is $session_token coming from in this example? Depending on how you generated the access token, one of two things are happening:
You are not sending the correct access token.
The access token you are sending has expired.
If it's 2, you should have gotten a refresh token when the user authorizes your app. The PHP SoundCloud SDK has a accessTokenRefresh() method that you can use in this scenario.
You need a non-expiring token.
When authorizing, the param scope defaults to "*".
Specify the scope and retrieve the token like this:
$soundcloud->getAuthorizeUrl(array('scope'=>'non-expiring'))
See: http://developers.soundcloud.com/docs/api/reference#connect
(Quite old question, but just ran into this myself. When the token is expired you don't get feedback from the API other then the 401 error, leaving you in the dark.)