What method should I use for a login (authentication) request? - authentication

I would like to know which http method I should use when doing a login request, and why? Since this request creates an object (a user session) on the server, I think it should be POST, what do you think? But since the login request should be idempotent, it could be PUT, couldn't it?
Same question for a logout request, should I use the DELETE method?

If your login request is via a user supplying a username and password then a POST is preferable, as details will be sent in the HTTP messages body rather than the URL. Although it will still be sent plain text, unless you're encrypting via https.
The HTTP DELETE method is a request to delete something on the server. I don't think that DELETING an in memory user session is really what it's intended; more it's for deleting the user record itself. So potentially logout can be just a GET e.g. www.yoursite.com/logout.

I believe that you can translate LOGIN & LOGOUT methods into basic CRUD operations CREATE & DELETE. Since you are creating a new resource called SESSION and destroying it when logging out:
POST /login - creates session
DELETE /logout - destroys session
I would never do LOGOUT as GET just because anyone could make an attack just simply by sending an email with IMG tag or link to website where such an IMG tag exists. (<img src="youtsite.com/logout" />)
P.S.
Long time I was wondering how would you create a RESTful login/logout and it turned out it's really simple, you do it just like I described: use /session/ endpoint with CREATE and DELETE methods and you are fine. You could also use UPDATE if you want to update session in one way or another...

Here is my solution based on REST guides and recommendations:
LOGIN - create a resource
Request:
POST => https://example.com/sessions/
BODY => {'login': 'login#example.com', 'password': '123456'}
Response:
http status code 201 (Created)
{'token': '761b69db-ace4-49cd-84cb-4550be231e8f'}
LOGOUT - delete a resource
Request:
DELETE => https://example.com/sessions/761b69db-ace4-49cd-84cb-4550be231e8f/
Response:
http status code 204 (No Content)

For login request we should use POST method. Because our login data is secure which needs security. When use POST method the data is sent to server in a bundle. But in GET method data is sent to the server followed by the url like append with url request which will be seen to everyone.
So For secure authentication and authorization process we should use POST method.
I hope this solution will help you.
Thanks

Regarding the method for logging out:
In the Spring (Java Framework) documentation, they state that a POST request is preferred, since a GET makes you vulnerable to CSRF (Cross-Site Request Forgery) and the user could be logged out.
Adding CSRF will update the LogoutFilter to only use HTTP POST. This ensures that log out requires a CSRF token and that a malicious user cannot forcibly log out your users.
See: https://docs.spring.io/spring-security/site/docs/current/reference/html/web-app-security.html#csrf-logout
Logging in should also use POST (body can be encrypted, see the other answers).

For Login I use POST, below is my code for LOGIN method
I used Nodejs with Express and Mongoose
your router.js
const express = require("express");
const router = express.Router();
router.post("/login", login);
your controller.js
export.login = async(req, res) => {
//find the user based on email
const {email, password} = req.body;
try{
const user = awaitUser.findOne({email});
if(user==null)
return res.status(400).json({err : "User with
email doesnot exists.Please signup"});
}
catch(error){
return res.status(500).json({err :
error.message});
}
//IF EVERYTHING GOES FINE, ASSIGN YOUR TOKEN
make sure you have JWT installed
const token = jwt.sign({_id: user._id}, YOUR_SECRET_KEY);
res.cookie('t');
const {_id, name, email} = user;
return res.json({token, user : {_id, email, name}});
}

Related

How to judge the success of third-party authentication?

My front-end is built with vue, and the back-end is with golang. My questions are 1. When I click the button to request a third-party login, how do I judge that the third-party authentication is successful? 2. And how do I get the data on the server side
The second question I think of is to save data on the server side through cookies and session, and the front end can get information through the cookie HTTP request header. Is there a more concise way
The second question, how can I judge the success of the third-party authentication?
My jump Url code is
/// vuex
async accountLoginAction({ commit, dispatch }, payload: any) {
const from: string = payload
window.location.href = getMixinUrl(from)
},
Through this code, the page can be jumped to a third party, then how can I judge that the authentication is successful? And how to request data gracefully when the judgment is successful.

How to secure an endpoint

I have an endpoint written in expressjs
router.post("/mkBet", async (req, res) => {
console.log(req.body)
const betToPush = new Bet({
addr: req.body.address,
betAmount: req.body.amount,
outcome: req.body.didWin,
timePlaced: Math.round(+new Date()/1000)
})
try {
const newBet = await betToPush.save()
res.status(201).json(newBet)
} catch(err) {
res.status(400).json({message: err.message})
}})
And I am trying to make it so that it can only be called when an action is performed on the frontend. So users cannot call it with custom arguments to make it so the outcome is always true. What would be the best way to achieve this?
It is not possible to securely tell what client sent the request. In other words, a request from your client and a different one can be identical in general.
Talking about unmodified browsers (as opposed to non-browser tools like Postman), you can tell the origin of the request (~the url loaded in the browser when the request was sent) with some confidence from the Origin and Referer request headers. However, your backend needs authentication and authorization anyway.
With the latter two in place, ie. with proper security implemented on the server-side, it doesn't matter anymore what client sends the requests.

Add custom session data to jsoup POST request in clojure

I am testing my first clojure ring application with midje and jsoup.
The app uses ring-session to add session for logged-only pages.
Session is not a cookie, neither part of the header of the request and I dont know how to add it to perform a post request correctly on logged pages...
A POST request in jsoup is something like:
(-> (Jsoup/connect "http://localhost:3001/sendto")
(.userAgent "...")
(.header "Content-Type","application/x-www-form-urlencoded")
(.data "amount" amount)
(.data "to" email)
(.data "sendto-submit" "Send")
(.post))
Altough this will not work when trying to perform a request against a logged-only url.
I'd have to add the session object, that in my case is something like:
{:session {:auth {:email "name#email.com"}}}
to the request, but so far neither (.cookie) nor (.data) worked...
Any help is suuuuper welcome :)
Without knowing the server side config, it's hard to give exact advice, but you have to remember the cookie you get on login and send it with the requests.
What you see on the server as {:session {:auth ,,,}} is the result of the session wrapper loading server side stored data into the request.
So basically:
you send a request, that starts a session (e.g. your login)
the server sends you a cookie back and stores informations about the login in it's session storage
you send a request, that includes that cookie
the server looks the cookie up in the session storage and injects the data associated with it in the request.
See the source/doc

Auth0: Validating id_token/JWT on UI (javascript) level

Update March 2019
I just went over this question again; the Auth0's github code has been updated in December 2018. They are now storing 'access_token','id_token' and 'expire_at' into the object/session, instead of localstorage and using now an 'isLoggedIn' flag to mark if authenticated or not. Check the pull request and these 2 lines in the specific commit: line1 and line2.
If you do not need to re-validate 'id_token' - like I was doing in the original question - that might be an alternative. Otherwise check original question.
Original Question
We are using auth0 for one of our clients. One stack that we are using it for is:
React/Redux UI
NodeJS backend
So we are using a cross origin authentication using implicit grant for that, using JWT with an RS256 algorithm. We also refresh tokens in background using silent authentication.
I was able to validate 'access_token' on the API (nodejs) side using node-jwks-rsa for express
On the UI level, after going through the source code of the auth0-js library I noticed that the "parseHash" method used in their provided react samples, actually validates tokens before we store them in localstorage, ie on successful authentication. Mainly this line in the source code.
Then I used their sample code that allows us to check if a user is authenticated, method isAuthenticated().
Problem with the isAuthenticated() method
From a security perspective, if later on (post authentication) a user of the application decided to manually modify the 'expire_at' label in the storage, they could get away as indeed authenticated. While of course there is additional security checking in our app, I wanted to update this function to validate 'id_token'. So far, I couldn't find any example in auth0's online docs for how to do that.
After digging in their source code I found a method validateToken that is being used. So I decided to leverage it in one of our functions:
import IdTokenVerifier from 'idtoken-verifier'
.... Some code in here ....
reValidateToken() {
return new Promise((resolve, reject) => {
// Both of these are stored in localstorage on successful authentication, using the parseHash method
let id_token = localStorage.getItem('id_token');
let transactionNonce = localStorage.getItem('app_nonce');
this.webAuth.validateToken(id_token, transactionNonce, function(
validationError,
payload
) {
if (!validationError) {
resolve('no validation errors for id_token');
}
if (validationError.error !== 'invalid_token') {
reject(validationError.error);
}
// if it's an invalid_token error, decode the token
var decodedToken = new IdTokenVerifier().decode(id_token);
// if the alg is not HS256, return the raw error
if (decodedToken.header.alg !== 'HS256') {
reject(validationError);
}
});
});
}`
Now, for it to succeed; we store the nonce in localstorage after successful authentication, does this approach create back doors for potential security holes? if it does; what is best practice to validate RS256 JWT id_token(s) on a UI level?

OWIN cookie authentication OnValidateIdentity should be called on every request?

Perhaps I am misunderstanding how this works, but I thought the OnValidateIdentity would be called on every HTTP request to the server. I see it get hit on initial login (a bunch of times, so it looks like it is every HTTP request on initially), but then it doesn't seem to get called again. I let my app sit there until it should be expired, but it never gets hit again on subsequent requests to the server, until I logout and login again.
I have set my expiry very low and turned off sliding expiration to see if I could get it to fail, but to no avail.
Should I not see the OnValidateIdentity get called on every HTTP request? Ultimately, I really just want a cookie expiry to result in a logout. I assumed I had to check the expiry on each request in the OnValidateIdentity, but if this is not the way to do it please let me know!
Am I misunderstanding how this work, or how I should be using cookie expiries to force a logout?
Here is my basic setup:
app.UseCookieAuthentication(New CookieAuthenticationOptions() With
{
.AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
.AuthenticationMode = AuthenticationMode.Active,
.ExpireTimeSpan = TimeSpan.FromMinutes(1.0),
.SlidingExpiration = False,
.Provider = New CookieAuthenticationProvider() With
{
.OnValidateIdentity = SecurityStampValidator.OnValidateIdentity(Of ApplicationUserManager, ApplicationUser, Integer)(
validateInterval:=TimeSpan.FromMinutes(1.0),
regenerateIdentityCallback:=Async Function(manager, user)
Return Await user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie)
End Function,
getUserIdCallback:=Function(id) id.GetUserId(Of Integer)())
},
.LoginPath = New PathString("/Account/Login")
})
Probably a bit late...
To use cookie Expiry, that's delegated to the browser. If a cookie expires, then the browser wouldn't send it.
OnValidateIdentity is called on every request. If you want to debug it, pull it out into a new method and debug from that method instead.
However, the identity itself is only validated against the database when the validationInterval is passed.