How to send the JWT token to the client with feathersjs-authentication? - node.js

I'm using local authentication in my feathersjs REST-API application, but after the user is authenticated, instead of sending me the authentication token, feathers is sending the following HTML as a response to the authentication request:
<body>
<img class="logo" src="alongbase64string" alt="Feathers Logo">
<main>
<h1 class="center-text">Success</h1>
<h3 class="center-text">You are now logged in. We've stored your JWT in a cookie with the name
<span class="italic">"feathers-jwt"</span> for you. It is:
</h3>
<pre id="token"></pre>
</main>
<script type="text/javascript">
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
var token = getCookie('feathers-jwt');
var el = document.getElementById('token');
el.innerHTML = token;
</script>
which prints the following page:
I think this would work good enough if I was sending the request from a web page, but in my case I need to get the token, because the client is a mobile app, not a web browser, so cookies won't work for me.
Is it possible for me to make feathersjs send the token in the response? Something like:
{
token: 'açldkjfaçldkfjçasdkfjdçakfjd'
}
This way I could store the token in the mobile app, and use it to authenticate further requests to my feathersjs API server.
For now I won't put any more code here, because the application was made entirely with the console commands available by feathersjs, like feathers generate but if anyone needs to understand more about the code, just let me know, and I will edit the question adding more details.

You have to make sure to set the Accept header in your request to application/json otherwise it'll assume HTML and send the page you are seeing.

Use the local middleware instead of the socket scheme referenced in the question.
POST'ing login data to /auth/local will yield
{
"token": {JWT},
"data": {
"email": "admin#feathersjs.com",
"id": 0
}
}
Your client can pull values from that JSON response and handle them appropriately.
Most anything beyond that will require modifying the stock Feathers demo.

Related

Redirect even if user uses back button (Node.js)

I have made a login system with jwt and, basically, the user redirects to the homepage (homepage/) if login (homepage/login) is successfull. After that, even if the user types (homepage/login) in the url, they get redirected back to the homepage because (and as long as) they have the jwt token.
I have the following code:
app.get('/login', (req, res) => {
const token = req.cookies.jwt
if(token) {
res.redirect('/')
} else {
res.render('login')
}
})
HOWEVER, if the user goes to (homepage/login) through the "back button", they are no longer redirected even though they have the token.
How can I include a redirect if the back button is pressed ?
Redirection is happening on client side.
So, simply include a frontend javascript code that checks if token is there. If not present, redirect.
In html code, include this script in head tag (assuming you are using localstorage to store token:
<html>
<head>
..
..
<script>
const token = localstorage.getItem("token");
if(token == null) {
window.location.replace("-path-to-home-page-");
}
</script>
</head>
<body>
..
..
..
</body>
</html>

How to add basic authentication header to form

I'm using node server built on https://github.com/passport/express-4.x-local-example(just changed app.get('/login'... to app.post('/login' … in server.js.
In pug, I created a page with a login form based on https://www.w3schools.com/howto/howto_css_login_form.asp and when I submit form (input names changed to username and password, method="post", action "/login") everything works fine. Since I don't want to send passwords in a body without authentification, I need to add basic auth to my post request.
How do I do that?
I tried adding event listener submit to my form and stopping default action with event.preventDefault();. I then created new XMLHttpRequest(), set request header to basic auth and sent the XML request to server. When using console I can verify the request came in, did the job, but the reply from server (which should redirect) returned to my XML request, not actually redirecting the page.
When I try sending the same POST request via POSTMAN, the response is a redirect page.
If I remove event listener the form gets submitted and everything works fine (but without adding auth headers).
doctype html
head
meta(charset='UTF-8')
title Login
link(rel='stylesheet', href='stylesheets/main.css')
link(rel='icon', type="image/png", href='favicon.png')
body
form(action='/login', id='form1' method='post')
.imgcontainer
img.avatar(src='images/img_avatar2.png', alt='Avatar')
.container
label(for='username')
b Username
input(type='text', placeholder='Enter Username', name='username', autofocus, required, id='uname')
label(for='password')
b Password
input(type='password', placeholder='Enter Password', name='password', required, id='pword')
button(type='submit') Login
script.
document.getElementById("form1").addEventListener("submit", submitFunction);
function submitFunction() {
event.preventDefault();
var usr=document.getElementById('uname').value;
var pwd=document.getElementById('pword').value;
var obj = {'username' : usr, 'password' : pwd};
var request = new XMLHttpRequest();
request.open("POST", "/login", false);
request.setRequestHeader('Authorization', 'Basic Y2xpZW50SUQ6c2VjcmV0S2V5');
request.setRequestHeader('Content-Type', 'application/json');
request.send(JSON.stringify(obj));
}
Authentication is not needed and will not make your request secure as without encryption the HTTP request is still plain text.
Encryption will make your request secure, your page and API should both use HTTPS, and when using encryption you do not need the additional authentication.
I found a workaround to include headers. First of all, I was using the wrong passport strategy. I used local and should have used ('passport-http').BasicStrategy. Here is an example
https://github.com/passport/express-3.x-http-basic-example
I added a placeholder for response in my XMLHttpRequest so the script part of my pug looks now like
script.
document.getElementById("form1").addEventListener("submit", submitFunction);
function submitFunction() {
event.preventDefault();
var username = document.getElementById('uname').value;
var password = document.getElementById('pword').value;
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (this.readyState == 4) {
// Typical action to be performed when the document is ready:
// accept and redirect code in here based on the answer from the server
}
};
request.open("POST", "/login", false);
request.setRequestHeader('Authorization', "Basic " + btoa(username + ":" + password));
request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
request.send();
}
of course, as Absor said ih his answer (thank you) it's still just plain text so maybe it will not add security to my request.

How to validate csrf token at server side(nodeJs) sent via ajax call

In my nodeJs application i'm using quite a few Ajax calls and want to guard those call against the CSRF attacks.
I am using csurf for this and it works perfectly fine as long as the request is normal request. In this case all we need to do is just pass the token from route to view and embed it to your form.When form is submitted with the token csrf takes care of it. if it doesn't match then invalid csrf token error is shown.
But when it comes to Ajax call can't figure out how to do this to guard those ajax calls,this is what i have got to know after googling for few hours.Since we need a token for Ajax call,can add to a meta tag or something to the main page.Upon each Ajax call we have to find the csrf token and either add it to the request header or body i,e payload.
Use a middleware to save the token in your response.
var csrf = require('csurf');
var csrfToken = csrf();
......some code here
app.use(csrfToken);
app.use(function (req, res, next) {
res.locals._csrf = req.csrfToken();
next();
});
We need to add it to layout or something so that we can grab it for each Ajax call.
<head>
<title>{{title}}</title>
<meta name="_csrf" content="{{_csrf}}"/>
....
</head>
For setting up the token in Ajax call i did something like this.
var csrf_header = 'X-CSRF-Token';
var setToken = function (securityToken) {
jQuery.ajaxPrefilter(function (options, _, xhr) {
if (!xhr.crossDomain) {
xhr.setRequestHeader(csrf_header, securityToken);
}
});
};
Is it wise to add token to request header or go ahead with adding it to request body ?
Upto this point i am good but how can we validate the token we are gonna sent on server.
Any help or any pointer will be much appreciated!!

Performing simple authentication in Angular and Node

I have been struggling with performing simple authentication in my angular node application. I am well aware that there are ready to use angular-express yeoman kits out there. But I want to understand this fuly and hence the attempt.
What I have been able to do so far is create a login form which connects to node server. It sens login name and password and receives a response back.
Where I am stuck is how to convert this simple interaction into a authentication process.
My Directory structure is as below
--ParentDirectory/
-client/
--css/
--lib/ /*all angular and jquery library files*/
--src/ /* All other angular modules, directives etc */
--app.js
--index.html /* default page associated with app.js
--login.js /*module login is independent of app.js module */
--login.html
-server/
--server.js /*restify code sits here */
app.js is where the main app resides.
So far it looks like :
angular.module('app',['']);
angular.module('app').controller('mainCtrl',function($scope){
$scope.hello = "Hello World";
});
Now First things first.. when a user visits my website i.e index.html page.. they will end up in this app and I would like for them to be re-directed to login.html page if they are not authenticated.
Any clues on how to achieve that ?
Moving on..
Login.html simply asks for a username and password (not showing the code here to keep things compact)
Login.js looks like this:
angular.module('loginApp',['common.webservice'])
.controller('loginCtrl',['$scope','WSLogin','$location','$window','Authen',function($scope,WSLogin,$location,$window,Authen){
$scope.message;
$scope.submit = function(){
var temp = {logonID: $scope.username,password: $scope.password};
WSLogin.save(temp,function(result){
Authen.isLogged = true;
$window.sessionStorage.token = result.token;
$scope.message = result.token;
$location.path("/main");
},function(err){
$scope.message = "Authentication failed. Pls retry";
});
};
$scope.logout = function(){
if (AuthenticationService.isLogged){
Authen.isLogged = false;
delete $window.sessionStorage.token;
$location.path("/");
}
}
}])
.factory('Authen', function() {
var auth = { isLogged :false };
return auth;
});
WSLogin is a resource that connects to the node serve on the path user/authenticate. This webservice is working fine so far.
[not showing the code here to keep things compact]
The server.js file looks like this:
var restify = require('restify');
var server = restify.createServer({
log: log,
name: 'demo'
});
server.listen(12345, function(){
console.log('%s listening at %s', server.name,server.url);
});
server.post('/user/authenticate',function(req,res,next){
if (!(req.params.logonID === "test" && req.params.password === "test")) {
res.send(401, 'Wrong user or password');
return;
}
var profile = {
first_name: 'John',
last_name: 'Doe',
email: 'john#doe.com',
id: 123
};
// we are sending the profile inside the token
res.json({token:profile);
});
How can I patch things up so that this somewhat resembles a authentication system.
I have picked up tips from various blogs, sites etc.. but no luck implementing them.
I understand you want to know how things are built, but I highly recommend picking up Passport to use on the Node/server side for authentication. With that said, in your implementation of login, it might be easier to include a cookie with the token in the response, rather than returning the token in the response. The code can then return a 200 (or 201) response code to indicate the login was successful, but by moving the token to a cookie, the client code doesn't have to deal with sending the token on future requests -- it's sent automatically in a cookie.
Moving on to your client side questions, keep in mind that you would enable security to protect resources on the server side. Anything you put in your client side JavaScript code can be read by anyone. So in the end these APIs that return protected data are the ones that need to be protected. Again, Passport provides an easy way to protect an API, but you could validate that each API request contains this token (or cookie) prior to providing the data.
In the case that the request is not authorized (it doesn't contain the token, or the token is invalid), you can return a 401 (Unauthorized) response. In the client side code, you can check for this and automatically route the user to the Login page.
Using Angular, one pattern to accomplish this is to use httpProvider Interceptors which allow you to hook into each HTTP request. You could check for a responseError with a status of 401, and route them to the Login page.

How to get an Instagram Access Token

I'm really struggling in how I'm meant to get my access token for Instagram,
I've registered a new client and then I used this URL
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code
to fill in the clients ID and redirect Url.
I then was redirected to a page where it displayed a code in the Url but from there I don't have a clue where id then get my access token.
Link to oficial API documentation is http://instagram.com/developer/authentication/
Longstory short - two steps:
Get CODE
Open https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code with information from http://instagram.com/developer/clients/manage/
Get access token
curl \-F 'client_id=CLIENT-ID' \
-F 'client_secret=CLIENT-SECRET' \
-F 'grant_type=authorization_code' \
-F 'redirect_uri=YOUR-REDIRECT-URI' \
-F 'code=CODE' \
https://api.instagram.com/oauth/access_token
Almost all of the replies that people have posted so far only cover how to handle access tokens on the front end, following Instagram's client-side "implicit authentication" procedure. This method is less secure and unrecommended according to Instagram's API docs.
Assuming you are using a server, the Instagram docs sort of fail in providing a clear answer about exchanging a code for a token, as they only give an example of a cURL request. Essentially you have to make a POST request to their server with the provided code and all of your app's information, and they will return a user object including user information and the token.
I don't know what language you are writing in, but I solved this in Node.js with the request npm module which you can find here.
I parsed through the url and used this information to send the post request
var code = req.url.split('code=')[1];
request.post(
{ form: { client_id: configAuth.instagramAuth.clientID,
client_secret: configAuth.instagramAuth.clientSecret,
grant_type: 'authorization_code',
redirect_uri: configAuth.instagramAuth.callbackURL,
code: code
},
url: 'https://api.instagram.com/oauth/access_token'
},
function (err, response, body) {
if (err) {
console.log("error in Post", err)
}else{
console.log(JSON.parse(body))
}
}
);
Of course replace the configAuth stuff with your own information. You probably aren't using Node.js, but hopefully this solution will help you translate your own solution into whatever language you are using it in.
I got the same problem before, but I change the url into this
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
The Instagram API is meant for not only you, but for any Instagram user to potentially authenticate with your app. I followed the instructions on the Instagram Dev website. Using the first (Explicit) method, I was able to do this quite easily on the server.
Step 1) Add a link or button to your webpage which a user could click to initiate the authentication process:
Get Started
YOUR_CLIENT_ID and YOUR_REDIRECT_URI will be given to you after you successfully register your app in the Instagram backend, along with YOUR_CLIENT_SECRET used below.
Step 2) At the URI that you defined for your app, which is the same as YOUR_REDIRECT_URI, you need to accept the response from the Instagram server. The Instagram server will feed you back a code variable in the request. Then you need to use this code and other information about your app to make another request directly from your server to obtain the access_token. I did this in python using Django framework, as follows:
direct django to the response function in urls.py:
from django.conf.urls import url
from . import views
app_name = 'main'
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^response/', views.response, name='response'),
]
Here is the response function, handling the request, views.py:
from django.shortcuts import render
import urllib
import urllib2
import json
def response(request):
if 'code' in request.GET:
url = 'https://api.instagram.com/oauth/access_token'
values = {
'client_id':'YOUR_CLIENT_ID',
'client_secret':'YOUR_CLIENT_SECRET',
'redirect_uri':'YOUR_REDIRECT_URI',
'code':request.GET.get('code'),
'grant_type':'authorization_code'
}
data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
response_string = response.read()
insta_data = json.loads(response_string)
if 'access_token' in insta_data and 'user' in insta_data:
#authentication success
return render(request, 'main/response.html')
else:
#authentication failure after step 2
return render(request, 'main/auth_error.html')
elif 'error' in req.GET:
#authentication failure after step 1
return render(request, 'main/auth_error.html')
This is just one way, but the process should be almost identical in PHP or any other server-side language.
The easy way that works in 2019
Disable implicit oauth under the security auth and THEN load this:
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
Specify REDIRECT-URI in your account and type it exactly as specified.
The access token is returned as a URI fragment after you authorize the application to use your Instagram data. It should look something like the following:
Try this:
http://dmolsen.com/2013/04/05/generating-access-tokens-for-instagram/
after getting the code you can do something like:
curl -F 'client_id=[your_client_id]' -F 'client_secret=[your_secret_key]' -F 'grant_type=authorization_code' -F 'redirect_uri=[redirect_url]' -F 'code=[code]' https://api.instagram.com/oauth/access_token
100% working this code
<a id="button" class="instagram-token-button" href="https://api.instagram.com/oauth/authorize/?client_id=CLIENT_ID&redirect_uri=REDIRECT_URL&response_type=code">Click here to get your Instagram Access Token and User ID</a>
<?PHP
if (isset($_GET['code'])) {
$code = $_GET['code'];
$client_id='< YOUR CLIENT ID >';
$redirect_uri='< YOUR REDIRECT URL >';
$client_secret='< YOUR CLIENT SECRET >';
$url='https://api.instagram.com/oauth/access_token';
$request_fields = array(
'client_id' => $client_id,
'client_secret' => $client_secret,
'grant_type' => 'authorization_code',
'redirect_uri' => $redirect_uri,
'code' => $code
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
$request_fields = http_build_query($request_fields);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_fields);
$results = curl_exec($ch);
$results = json_decode($results,true);
$access_token = $results['access_token'];
echo $access_token;
exit();
}
?>
This worked just fine for me:
http://jelled.com/instagram/access-token
FYI, I used it in combination with the jQuery Instagram plugin which you'll find here;
http://potomak.github.com/jquery-instagram
If you're looking for instructions, check out this article post. And if you're using C# ASP.NET, have a look at this repo.
By using https://www.hurl.it/ i was able to see this:
{
"code": 400,
"error_type": "OAuthException",
"error_message": "Matching code was not found or was already used."
}
so: you have to get new code for every request.
If you don't want to build your server side, like only developing on a client side (web app or a mobile app) , you could choose an Implicit Authentication .
As the document saying , first make a https request with
https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token
Fill in your CLIENT-ID and REDIRECT-URL you designated.
Then that's going to the log in page , but the most important thing
is how to get the access token after the user correctly logging in.
After the user click the log in button with both correct account and password,
the web page will redirect to the url you designated followed by a new access token.
http://your-redirect-uri#access_token=ACCESS-TOKEN
I'm not familiar with javascript , but in Android studio ,
that's an easy way to add a listener which listen to the event the web page override the url to the new url (redirect event) ,
then it will pass the redirect url string to you , so you can easily split it to get the access-token like:
String access_token = url.split("=")[1];
Means to break the url into the string array in each "=" character , then the access token obviously exists at [1].
go to manage clinet page in :
http://www.instagram.com/developer/
set a redirect url
then :
use this code to get access token :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>tst</title>
<script src="../jq.js"></script>
<script type="text/javascript">
$.ajax({
type: 'GET',
url: 'https://api.instagram.com/oauth/authorize/?client_id=CLIENT-‌​ID&redirect_uri=REDI‌RECT-URI&response_ty‌pe=code'
dataType: 'jsonp'}).done(function(response){
var access = window.location.hash.substring(14);
//you have access token in access var
});
</script>
</head>
<body>
</body>
</html>

Resources