I need to make a request with e-mail and password. E-mail and password are Strings sent to my repository class. And the password need to be encoded with Base64.
I'm using Retrofit 2.
I know I need to use RequestBody class, but how can I can make the request?
This is the code from Rest interface:
#POST("login")
Call<String> login(
#Body RequestBody payload
);
In the repository, I have this to encode the password:
String encodedPassword = Base64.encodeToString(password.getBytes(), Base64.NO_WRAP);
But I need to initialize the requestBody with the email and the encodedPassword variables, to make the request.
Call<String> call = getApi().login(requestBody);
Is this really the right way?
How the requestBody attribute is initialized?
It all depends on what your API expects.
If your API expects an object encoded as JSON/XML, you send it in the request body.
For login credentials, most common is to send them as FormUrlEncoded data.
As an example:
#POST("/posts")
#FormUrlEncoded
Call<String> login(#Field("email") String email,
#Field("password") String password);
But as I said it all depends on what the API endpoint expects.
I also don't get why you need to Base64 encode the password, it doesn't add any additional security over the plain text over SSL, so you may double check this with the API documentation also.
Related
May be this will be silly question but I/m curious about that. I'm new to React-js and node-js backend. I'm save jwt token in web browser local storage and decode that token in react js frontend. my question is that safe use jwt decode method in front-end because someone can also decode token if they know token?
Yes, it is.
The idea behind JWTs isn't that they can't be decoded, in fact it's the exact opposite. They're designed for use in distributed systems. Instead they are secure, because they can only be generated using a secret key, which should only be available on the server-side of your application.
A JWT actually comprises three parts - headers, payload, and signature - with the headers, payload, and secret key being combined and hashed to form the signature.
This signature is then used to validate that the headers and payload haven't been modified. If they have, the signature would no longer match.
JWT codes have 3 separate part that separated with .
Public part which contains
HEADER:ALGORITHM & TOKEN TYPE
PAYLOAD:DATA
and a VERIFY SIGNATURE which guarantee your token is valid or not.
The public part can be extracted by everyone who have the token
JWT decode only look for public part so it is totally safe to do that in your front-end code.
An example:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
>> after decode
HEADER:ALGORITHM & TOKEN TYPE
{
"alg": "HS256",
"typ": "JWT"
}
PAYLOAD:DATA
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
The answer is yes and no, in case you have some user identifying information (like userId) and u are okay with that data going out, then yes u can decode it in the front end. If you are gonna store some sensitive information on the token then no. (This is a bad practice). Also note that the payload cant be modified. Even if modified the signature wont verify the token. So the best practice will be not to have sensitive data in the payload.
I am using express. I am getting json web token BACK. In java script for example if i want to see what is in the payload i will use window atob method.But i need to do this also in back end so to make only admin users to acccess some route.How can i decode the payload from json web token so i get back for example the json object.
You can use a Lib like jsonwebtoken
https://www.npmjs.com/package/jsonwebtoken
Example:
var decoded = jwt.verify(YOUR_TOKEN, 'YOUR_SECRET_KEY')
That way you can check it is your token and get the decoded JSON object
I am trying with node js request module to post some formData. My formData contains fields (file attachments) which I have to send with same name to the server. But my formData is being sent with only one attachment which is the last I have given in the set.
I want to know how to post with formData having same name for more than one field.
I can do that with unirest module in node js. I was having trouble with the authentication. But anyway if your server is using Basic auth you can encode your username and password string with base64 and set the Authorization header with that value. I am posting my answer because I took one day to figure out how to post attachments with same field name and finally unirest gave me a solution.
How to decode the id_token received from oauth2Client.getToken to get access to the JWT JSON fields email, sub, ..? Is there a function included in the google-api-nodejs-client lib?
In https://developers.google.com/accounts/docs/OpenIDConnect in says:
Since most API libraries combine the validation with the work of decoding the base64 and parsing the JSON, you will probably end up validating the token anyway as you access the fields in the ID token.
oauth2Client.getToken(req.query.code, function(err, tokens) {
// how to decode tokens.id_token to get
});
According to RFC, the JSON Web Token, when encoded, is composed of three parts (each part being a base64-encoded JSON object), separated by dots:
Header
Actual data
Signature
The header is pretty much a constant when used with Google APIs. You are going to need the second part.
To visualise this even better, take a look at jwt.io - it will show you the exact structure of the encoded token, in colours!:)
I recommend that you study carefully how it works, then install an npm module (there's aplenty around, search for jwt) to do the actual decoding for you.
here is the documentation
Just in case the Google documentation would be refactored in the future:
const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client(CLIENT_ID);
async function verify() {
const ticket = await client.verifyIdToken({
idToken: token,
audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]
});
const payload = ticket.getPayload();
const userid = payload['sub'];
// If request specified a G Suite domain:
// const domain = payload['hd'];
}
verify().catch(console.error);
Also available here
Note that I was using #googleapis/oauth2 instead of google-auth-library but I noticed #googleapis/oauth2:
[Deprecated] Obtains end-user authorization grants for use with other Google APIs.
So I guess google-auth-library is the right choice.
I am using a combination of Node.js and Passportjs on the server-side, and Emberjs on the client side for an app. My current Authentication strategy is to use Passport-Local to authenticate users with normal email/password combinations as standard, and then hook in a session creation mechanism to generate an Authentication Token, which is saved into a separate table, and passed back to the user for use in any further protected routes. (passed in the REST header).
Creation of the token is fine, i'm doing that without issue, however i'm struggling to work out if I need an extra step.
Currently, I generate the token with node-jwt-simple by using a random node-uuid pass as the payload, and the users UID (another node-uuid) as the secret. I then save this to a $.cookie on the clientside, and to a table on the serverside, along with a creation date.
Obviously, one of the steps in node-jwt-simple is to encode the token. There is also a decode function provided. My question is, do I need to decode the token into something when I am doing my auth checking, or is simply checking the user's session cookie (REST header) for a match against the token in the database sufficient? I wouldn't want to go to all the effort of having generated a token, only to then miss an important step, but i'm not seeing how I could decode it into anything that would provide any additional useful security.
UPDATE:
I think I worked this out last night:
The solution seems to be to use the User's UID as the payload for JWT, with a static string as the secret (taken from something like a server environment variable or similar), and then only store the encoded token in the database. Pass the token back to the client for re-auth, then when the client attempts to access a protected route, they must pass their UID along with the encoded token to the server, which is then decoded, and the decoded payload compared to the UID that has been passed. If they match, the auth is successful, otherwise the token is destroyed and the user has to log in again.
By doing this, it makes the store of tokens effectively useless without knowing either the Secret key, or having the User's UID, but makes the auth process more secure.
If you don't validate the token, you could as well create some other random data to use as a session cookie, as long as it is unique and cannot be guessed by clients.
But as you already made a lot of effort, you could encode something useful in the token which tells you how long it is valid, e.g. an exp field, so you don't have to read from the database.
I'm not sure if I fully understand your JWT, but the problem I see is that you need information to decode the token which is probably not at your hand. So you have to do a search in your database.
I think it would be sufficient to use some random session key, e.g. following function:
var crypto = require('crypto');
/**
* Create random bytes and encode base64url.
* #param {int} [lengthInBytes=40] the size of the raw token in bytes
* (will be longer since base64url-encoded)
* #param {function} callback node-style callback-function;
* data-parameter is a string w/ a shortened (no trailing ==)
* base64url-encoded string of the generated bytes.
*/
exports.createRandomToken = function createRandomToken(lengthInBytes, callback) {
if (typeof lengthInBytes === 'function') {
callback = lengthInBytes;
lengthInBytes = 40;
}
crypto.randomBytes(lengthInBytes, function (ex, buf) {
if (ex) {
callback(ex);
return;
}
callback(null, buf.toString('base64')
.replace(/\//g, '_')
.replace(/\+/g, '-')
.replace(/=/g, ''));
});
};
Set expire time of the token as small as possible(5 min, 30 min, nor months neither years).
Use refresh token to get a new token and update refresh token every time you update old token (and when user is logged in, no doubt)
Do not store passwords, credit card numbers and any confidential informations in the token ( I'm shure, you know it :) )
Store all necessary information for checking privileges ( or checking ip, for example ). It is good for REST API and horizontal scaling.