Unknown Reason for JWT Tokens invalidation - angularjs

I'm facing very weird problem with my laravel-Angular application. I'm using Tymon JWT to refresh token on my every request. I'm using Satellizer library to handle these JWT-Tokens, however, Satellizer doesn't seem to have a response interceptor to capture the new token. Hence I wrote my own Interceptor to do so.
.factory('ResponseHttpInterceptor', function ($window) {
return {
response: function (response) {
if (response.headers('Authorization') != null) {
$window.localStorage.removeItem('satellizer_token');
$window.localStorage.setItem('satellizer_token', response.headers('Authorization').replace('Bearer ', ''));
}
return response;
}
}
})
This code basically captures the new token and replaces the existing token in local storage with the new token.
My test flow is:
Login -> Make who Am I call -> Logout
Upon Logout I receive an error Invalid token (this doesn't happen always. Sometimes the flow succeeds and sometimes it fails). This flow works perfect via REST Client postman. So I don't think there is any problem in my API's
Attaching image showing the new token being passed, after it is refreshed after my whoami call.
Upon logout I'm clearing the local storage. Can Anyone tell me what could be the reason for this?
EDIT
Route::group(['prefix' => 'api/v1_0'], function () {
Route::post('login', 'Auth\AuthControllerGeneral#postLogin');
Route::get('logout', ['middleware' => 'jwt.auth', 'uses' => 'Auth\AuthControllerGeneral#getLogout']);
Route::group(['middleware' => ['jwt.refresh', 'jwt.auth']], function() {
Route::get('whoami', 'Auth\AuthControllerGeneral#loggedInUserInfo');
});
});

Check you htaccess you should have below code there
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
And AuthContrller is same as https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/Controllers/AuthController.php
And Some people forget to check Authenticate middleware. Check this also
https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/Middleware/Authenticate.php
I suggest first try with default route as in demo
https://github.com/sahat/satellizer/blob/master/examples/server/php/app/Http/routes.php
And still you not get the solution then try with sample client end folder.
https://github.com/sahat/satellizer/tree/master/examples/client
Which you can put in your laravel public folder just to test.
I found everything working fine in satellizer but some people fails in configuring this.

Related

salesforce forcejs not getting refresh token

i am using forcejs in my angular app which is working fine and gives me accessToken. However, I am not able to get refreshToken to be able to renew accessToken as needed. The code is below
import { OAuth, DataService } from 'forcejs';
async loginSFDC(){
let callbackUrl = 'https://my.callback.url'
let oauth = OAuth.createInstance('client key','', callbackUrl);
oauth.login().then(
async (oauthResult) => {
DataService.createInstance(oauthResult);
console.log("Logged Into Salesforce Successfully:::" + JSON.stringify(oauthResult));
});
}
the above code is printing accessToken but no refreshToken. Please advise
i have also tried passing the 2nd parameter in createInstance as http://login.salesfoce.com?scope=full+refresh_token but that does not work as url gets constructed wrong on adding the scope=full+refresh_token
From looking at the source code of forcejs, you can use the refreshAccessToken() method with the DataService instance you created.
After some more debugging it is discovered that the refresh token shows up when my code is running on localhost but does not when it is deployed to the the webserver. i dont know how to debug further or fix it. but i have verified that this behavior is consistently reproducible

Meteor redirect client from server-side method

Meteor 1.6, React, React Router
Interfacing with Paypal billing-agreements
Client onClick event:
subPayPal(){
Meteor.call('paypal.getToken', this.props.user_id, (error, response) => {
if(error) {
console.warn(error);
}else{
console.log(response);
}
}
}
I'm calling the method on the server rather than on the client because I'm dealing with privileged info (usernames, passwords, tokens, etc). No problem here.
Server methods:
Meteor.methods({
'paypal.getToken': function getOauthToken(uid){
// simplified a bit
// check if current token valid
// set vars here, then go get token
axios.post(ppAPI, data, config)
.then( function(response) {
// save oAuth token
})
.catch( function(error){
// stuff here
})
// prepare another axios.post(), with oauth Token, to get a payment token
// and approval_url and execute_url from paypal
// call axios.post() and use data in response:
// with the approval_url in this reponse, I need to redirect
// the browser to the approval_url on paypal.com so that the user
// can sign into paypal, and ok the subscription agreement.
// once user 'ok' in paypal, the browser comes back to my site,
// where I render a 'cart' with a final 'ok, purchase' button.
return approval_url;
}
})
So, once I have the approval_url, I can send it back to the client, and when the client "sees" it, it can then call the React Router to the paypal.com site.
PROBLEM
The client's onClick method is obviously async and as soon as I click the initial onClick(), the console.log outputs undefined for process which makes perfect sense.
TRIAL 1
So, I tried using Meteor.apply in the client trying to make it synchronous, waiting for the server-side method to return the approval_url to no avail:
subPayPal(){
Meteor.apply('paypal.getToken', [{uid:user_id}], {
onResultReceived: (error, response) => {
if(error) console.warn(error.reason);
if(response) console.log('server response', response);
}
});
}
I also tried Meteor.call('paypal.getToken').then({ console.log(response) }).catch... to no avail either, as it is still async.
I've also tried try/catch blocks in the server-side method, to no avail. Whatever I try, the server-side code always runs as expected (with exception of the Meteor.call().then().catch() which just plain failed). I just can't seem to promise it, or return it.
TRIAL 2
The next thought would be not caring about the response on the client, if I could get the server-side method, with approval_url defined, to somehow call the React Router on the client and push the unique approval_url to it, but that doesn't make much sense to me how to wire that up.
THOUGHT 1
I guess I could use some "temporary" database collection, which is reactive, so that when the server-side method completes, it'll update (or insert/create) a document, and when the client 'sees' that, it could then call the React Router to redirect the browser to paypal.com. The collection document would have to hold the approval_url URI, which would then be passed down to the client. Not too sure how I'd wire the client to tell the Router when it sees the approval_url "appear".
Sooooo....
Any ideas? Is there more than one solution (and if so, what would be the best?).
I read somewhere that the app should logout the user, then the Router could redirect to paypal, but that doesn't help, as paypal.com redirects back to me, and I wouldn't want the user to have to log back in again.
THANKS.

Laravel 5.4 / Angular possible mishandled rejection due to cross origin request blocked

I am currently building an application using token based authentication with Angular and Laravel. I initially set things up just to test the API by creating a BookController . At first I was getting a Cross Origin Request Block error when I tried to call this data from Angular. However I managed to resolve this by adding the headers to my routes/web.php file. Here is the whole file. NB: After adding these headers I was succesfully able to use the API even from another domain
<?php
header('Access-Control-Allow-Origin: *');
header( 'Access-Control-Allow-Headers: Authorization, Content-Type' );
//Route::get('/', 'BookController#show');
//Route::resource('book/create', 'BookController#create');
Auth::routes();
Route::get('/', 'HomeController#index');
Route::resource('book', 'BookController');
Route::resource('authenticate', 'AuthenticateController', ['only' => ['index']]);
Route::post('authenticate', 'AuthenticateController#authenticate');
However I am currently following this tutorial to set up token based authentication. https://scotch.io/tutorials/token-based-authentication-for-angularjs-and-laravel-apps
To summarise , my issue is when I submit the form containing username and password I am getting the following errors. Below I will try elaborate a bit more but it is quite difficult as there is alot to it.
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://www.example.local/authenticate/.
(Reason: CORS header 'Access-Control-Allow-Origin' missing).
And
Possibly unhandled rejection:
{"data":null,"status":-1,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"http://www.example.local/authenticate/","data":{"email":"dasdas#Dasa.com","password":"fsdfd"},"withCredentials":false,"headers":{"Accept":"application/json,
text/plain,
/","Content-Type":"application/json;charset=utf-8"}},"statusText":""}
I am using Angular UI Router V 0.4.2 and satellizer. My Angular version is 1.6.2 It using a different domain than the API. Much like the working example above.
On the laravel side I also followed this tutorial to add middleware to attempt to resolve this but no luck.
http://en.vedovelli.com.br/2015/web-development/Laravel-5-1-enable-CORS/
I will also include my AuthenticateController.php file..
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use JWTAuth;
use Tymon\JWTAuth\Exceptions\JWTException;
use App\User;
class AuthenticateController extends Controller
{
public function __construct()
{
// Apply the jwt.auth middleware to all methods in this controller
// except for the authenticate method. We don't want to prevent
// the user from retrieving their token if they don't already have it
$this->middleware('jwt.auth', ['except' => ['authenticate']]);
$this->middleware('cors');
}
public function index()
{
// Retrieve all the users in the database and return them
$users = User::all();
return $users;
}
public function authenticate(Request $request)
{
$credentials = $request->only('email', 'password');
try {
// verify the credentials and create a token for the user
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'invalid_credentials'], 401);
}
} catch (JWTException $e) {
// something went wrong
return response()->json(['error' => 'could_not_create_token'], 500);
}
// if no errors are encountered we can return a JWT
return response()->json(compact('token'));
}
}
My issue is I do not even know if the "possibly unhandled rejection" is related to the "Cross-Origin Request Blocked" error. But I have to assume it is.
Can you recognise anything from my routes files that may be allowing one and not another?
EDIT:
I have noticed the difference between one request and another is that one is a GET request while another is an OPTIONS request. This may be the cause.
I have since added Header set Access-Control-Allow-Origin "*" to both the virtual hosts config file in Apache and to a .htaccess file in the root of the Laravel project. Still no change.
I am wondering is this related something in Angular
Your server code needs to handle that OPTIONS request by sending a headers-only response to it that includes the Access-Control-Allow-Methods: GET, POST, PUT, DELETE header and Access-Control-Allow-Headers: Authorization, Content-Type header.
Or you can just try using https://github.com/barryvdh/laravel-cors which makes all this easier.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests has general info you might want to read up on.

Spring + Angular / IE gets 403 on PUT (others don't)

I have a spring webapp with spring security(3.2.3, so no CSRF protection) and angular.
In a controller i have a method like this one to update the users pw:
#RequestMapping("/accountinfo/password", method = arrayOf(RequestMethod.PUT))
#ResponseBody
#Secured("ROLE_USER")
open fun updateOwnPassword(user: User, #RequestBody password: String) {
val editedUser = user
editedUser.password = encoder.encode(password)
userRepository.save(editedUser)
}
The request is done via angular Service:
function changeOwnPassword(newPassword) {
return $http
.put('accountinfo/password', newPassword)
.then(function (response) {
return response.data
});
}
This works fine in every browser i tested with. Except if using IE 11.0.35 in a Citrix environment (Works outside of it,but can't see any specific configuration).
In that case i get 403 on the Request. When i change the method to POST it works fine again. I could do that for every function where i got this problem of course, but that doesn't seem like a clean solution.
As far as my research goes, i think it's something wrong with the way the browser writes the Request, but that's were i can't find out what to do.
EDIT:
I compared the request headers of both IE 11.0.35 inside and outside of Citrix and they seem exactly the same. The only difference is that the working version uses DNT=1 and the non-working version as WOW64 in the User-Agent attributes?
UPDATE:
I found out that it happens with DELETE too
Found the problem: The client sends the Requests through an additional Proxy that doesn't like PUT and DELETE and just cuts the session cookies off of it. We are adressing that problem with putting the tokens in the header in the future.

OAuth2 with Satellizer and a generic OAuth2 provider

I'm having much trouble getting OAuth2 to work with a generic OAuth2 provider. Here's the situation.
A service provides an OAuth2 authentication method to where I want to authorize with. I've created an AngularJS app that has the following configuration for satellizer:
authProvider.baseUrl = 'http://localhost:3030/user/authorize';
$authProvider.oauth2({
name: 'customname',
url: '/token',
clientId: 'someapp',
requiredUrlParams: ['scope'],
scope: ['profile'],
authorizationEndpoint: 'http://location.to.oathserver',
redirectUri: 'http://localhost:3000'
});
The baseUrl points to my node server that should handle the middleware part.
I've also the following code that triggers the authentication part.
$scope.authenticate = function(provider) {
$auth.authenticate(provider)
.then(function(response) {
console.log(response);
})
.catch(function() {
//something went wrong
});
}
So far this all seems to work great and looks very similar to what is documented by Satellizer! Now once I start the angular app and start the authentication I see requests coming by that target my Node service.
Next I've my node.js service that hooks to the 'user/authorize/token' URL. Here's the code:
router.options('/authorize/token', function(req, res, next) {
//var token = req.header('Authorization').split(' ')[1];
res.end();
});
and:
router.post('/authorize/token', function(req, res, next) {
var authCode = req.param('code');
var cliendId = req.param('clientId');
var payload = jwt.decode(authCode, 'mySecret');
});
Here's where it all seems to go wrong. First I seem to get an OPTIONS request. I've not really an idea what to do with it as I can't seem to find anything in the documentation about an OPTIONS request. I thought it would might contain the 'Authorization' header but that doesn't seem the case so I close the connection with a res.end();
I also inspected the request in Chrome but I can't seem to find a header that has this exact name.
Next I get a POST request. This does seem to contain some things, hooray! I get the following object:
{
code: "ZFFeat9pWfHzw4rGmjFYwucPRMFnBOkd2odEObvo",
cliendId: "someapp",
redirectiUri: "http://localhost:3000"
}
This looks to me like the authorization code that I should have to decode. That's what you see me trying as well in the code above. Unfortunately this seems to throw me an error
Error: Not enough or too many segments
This tells me I'm doing probably something wrong, and I got stuck.
I do have some PHP code that seems to work for someone else but I don't fully understand and can't really relate the code to my code since PHP is not my speciality and node.js/JavaScript not his. So here goes the PHP code:
handle_cors(); // Handle CORS for cross domain requests
// Get JSON data
$input = json_decode(file_get_contents("php://input"), true);
// Create Provider
$provider = new SomeApp\OAuth2\Client\Provider\SomeApp([
'clientId' => 'someapp',
'clientSecret' => 'mySecret',
'redirectUri' => $input['redirectUri'],
]);
// Optional: Now you have a token you can look up a users profile data
try {
// Try to get an access token (using the authorization code grant)
$token = $provider->getAccessToken('authorization_code', [
'code' => $input['code']
]);
// We got an access token, let's now get the user's details
$user = $provider->getResourceOwner($token);
header('Content-Type: application/json');
$result = $user->toArray();
$result['token'] = create_token('my-example-key', $user->getId());
echo json_encode($result);
exit();
} catch (Exception $e) {
// Failed to get user details
exit('Oh dear...' . $e->getMessage());
}
Hopefully someone can help me out! Thanks in advance.
Sorry guys, I've been able to solve it myself. I found out that I was missing some URL's to POST to and GET from. After that the examples from Satellizer became clear and was able to use them almost as a carbon copy.

Resources