laravel / passport

Laravel Passport provides OAuth2 server support to Laravel.
https://laravel.com/docs/passport
MIT License
3.27k stars 777 forks source link

Getting Unauthenticated with a valid token #452

Closed lucassmuller closed 5 years ago

lucassmuller commented 7 years ago

I'm using Laravel with Passport to secure my API with OAuth. Although, after using a authorized token got with PostMan tool, in all my request using the Passport middleware i'm getting 401. I installed Laravel twice and looked all around the Internet without success and followed this page for installation: click here. There is some of my codes:

The route i'm trying to access:

Route::group(['middleware' => 'auth:api'], function(){

    Route::get('/user', function (Request $request) {
        return $request->user();
    });

});

The auth guard:

'guards' => [
    //..

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

And I'm using this header in my requests:

Accept: application/json
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImU5ZDcwZGY0ZjA2MGZhNDk5MzQ1ZjQyN2QxMWY1MDhkZDI2ZWQxODkzZDgxMTcxYWNkZGYxYTkxYzkwNWYxOGUyMTI2NzY0M2QwZmQyOWRiIn0.eyJhdWQiOiIxIiwianRpIjoiZTlkNzBkZjRmMDYwZmE0OTkzNDVmNDI3ZDExZjUwOGRkMjZlZDE4OTNkODExNzFhY2RkZjFhOTFjOTA1ZjE4ZTIxMjY3NjQzZDBmZDI5ZGIiLCJpYXQiOjE1MDE1Mjc2NDYsIm5iZiI6MTUwMTUyNzY0NiwiZXhwIjoxNTMzMDYzNjQ2LCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.dbJ4jddUZx1BT9X81LQIY-Dcx6xdDtmm2nH_C6t7rgFYzRTjab6w7T1NXfzKNlAeyi4iWJAARSBDI32vCeGuAy1ukFvr0qkoEp8UIZEqeeQYYam1Oox_0fuLlJyzwkOIospEc53KZBB0AQrPpW12abxZiZ6asQ9S4AbEJa5N95QFaYRMlxPxEMQOFt28v5148-shawcmtdV-AuAOpvsmap5_f4vQ-NY9R_He0NS4zOOQEY7sPIaRrsQ_XEAJwyiGnrUyufLr02T8wDUcqTskxCtizZx0aHN8i8lz9_X7xBFMHLj4zI4R3wfuZTWlOww07HdBt1oX8PAWvTgA0lw4Sq_xeKa3-MfuCasC4Vh_KWuvHQAfTIuCQw4lPOELfWWaeJTaEuuos7YFbOdoZIHoQWVs4lcisKpHuTGd8bzIPY9GGYsG26LRZB62vX358bijUuurh8p3ajPOt45tmvJnYyaHdf1gW5YwEqbtb07bohMrLFCNhYT0JFZvKa54FRRbB6BLA4lToDA4j1secMKan8mRMLwjEhqyPD0qxBswiMc127ryQ4CLvtKZ75Weno3oAnZ29ZkgtJCTESMzFjd41K-KgrV-s9KTWvfvmOECQUTQz6xUZ5WyVLzPZdBi6wNRYdAp4xRTA1RNUH3TSAP9qYt-xWTwNANXLvL5gBkBjQM
ibrahimSmuhammad commented 7 years ago

the same issue is there any solutions !!?

lucassmuller commented 7 years ago

Unfortunately, no. I still having this problem.

stefandb commented 7 years ago

I have the same problem. On a fresh installation.

bkkrishna commented 6 years ago

If you are in Apache server, I guess this should help you as it works on mine : Just add these lines on your .htaccess file :

RewriteEngine On RewriteCond %{HTTP:Authorization} ^(.*) RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

as stated in this thread.

Hope that helps.

eaguad1337 commented 6 years ago

Can anyone help me with the nginx configuration?

pdxbug commented 6 years ago

Something to do with: fastcgi_param HTTP_AUTHORIZATION $http_authorization; in the fastcgi_params global or nginx.conf file to pass the auth. See more here: https://stackoverflow.com/questions/46345676/rewrite-htaccess-to-nginx-with-http-authorization?rq=1

wqj97 commented 6 years ago

I'm using Laravel 5.6, this is my .htaccess file

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
#    RewriteCond %{HTTP:Authorization} ^(.*)
#    RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Still has same problem

MitchMilton commented 6 years ago

same here. Laravel 5.6 Literally tried every fix.

MitchMilton commented 6 years ago

@wqj97 did you get a solution?

wqj97 commented 6 years ago

@MitchMilton Yeah, I typed wrong token😂....

lerzenit commented 6 years ago

I'm having the same issue, with the same version of Laravel (5.6). Any ideas?

d0cm0d commented 6 years ago

I'm having the same issue with Laravel 5.6, Homestead 7.6m and nginx. Has someone figured out a solution?

lucassmuller commented 6 years ago

Unfortunately I did not find any solution and I left the thread but I will keep it open in case of any solution.

afanazmy commented 6 years ago

I have same problem

MitchMilton commented 6 years ago

For me, I found that I had typed 'user' instead of 'users' for the provider in config/auth.php . Your guards seem to be ok though.

sejanH commented 6 years ago

tried so many fixes for laravel 5.6 but not working. anyone solved this yet?

Sephster commented 6 years ago

What is the actual error being thrown? People have mentioned they are getting 401's but is there any specific error message you are receiving as well? This would help narrow down the problem.

andradedpg commented 6 years ago

Same problem. But Im observable this happened app inside docker. The same laravel app, in same server but ousite directory, works fine. Who knows?

wendyliga commented 6 years ago

same problem

stepri commented 6 years ago

Same problem here, also on Laravel 5.6, valet, nginx

stepri commented 6 years ago

Checked my token at jwt.io, it's a valid token but the authentication fails at this line. https://github.com/lcobucci/jwt/blob/3.3/src/Parser.php#L94 Token expected containing 3 dots (parts) but the token contains 6 parts

gabolecointere commented 6 years ago

Same Issue here with Laravel 5.6 and nginx with Docker. I tried this because it was the official package but I guess I will end on tymon/jwt-auth

nicolasflorth commented 6 years ago

Really no solution for this problem? I am in the same situation.

stepri commented 6 years ago

Upgrading to the lastest version of Laravel (clean project) fixed my problem.

a1tem commented 6 years ago

https://laravel.com/docs/5.6/upgrade#upgrade-5.6.30

Cookie Serialization Laravel 5.6.30 disables all serialization / unserialization of cookie values. Since all Laravel cookies are encrypted and signed, cookie values are typically considered safe from client tampering. However, if your application's encryption key is in the hands of a malicious party, that party could craft cookie values using the encryption key and exploit vulnerabilities inherent to PHP object serialization / unserialization, such as calling arbitary class methods within your application.

Disabling serialization on all cookie values will invalidate all of your application's sessions and users will need to log into the application again. In addition, any other encrypted cookies your application is setting will have invalid values. For this reason, you may wish to add additional logic to your application to validate that your custom cookie values match an expected list of values you expect; otherwise, you should discard them.

Configuring Cookie Serialization Since this vulnerability is not able to be exploited without access to your application's encryption key, we have chosen to provide a way to re-enable encrypted cookie serialization while you make your application compatible with these changes. To enable / disable cookie serialization, you may change the static serialize property of the App\Http\Middleware\EncryptCookies middleware:

/**

nadj commented 6 years ago

Hi all, I had this problem too. It happened to me after I updated laravel to 5.6.33 and passport, the problem was that I had an old cookie in my browser.

Removed the old cookie, logged in again and it works like a charm.

ilvalerione commented 6 years ago

After last update to laravel 5.6.33 I'm receiving always 401 Unauthorized error.

Before this update everything was working.

I'm trying to use my API through axios with CreateFreshApiToken middleware. I followed step by step guide from laravel doc to consume my api from javascript.

Login process works, but from authenticated web page ajax calls with axios receives always 401.

I deleted all cookies, but nothing.

nadj commented 6 years ago

Hi @ilvalerione try clearing caches in laravel with: php artisan cache:clear php artisan view:clear

ilvalerione commented 6 years ago

Hello @nadj I forgot this option.

I tried just now also re-deleting all cookies from Chrome but it's still not working.

a1tem commented 6 years ago

@ilvalerione check my comment above.

ilvalerione commented 6 years ago

Oooh wow! It's working now!

I'm not a passport package expert, but If passport does not work without cookie serialization it could be necessary to include this configuration in the official passport doc.

In the meantime @a1tem @nadj really thanks for your support!

schroedermatthias commented 6 years ago

Thanks, @a1tem

Adding

/**
/* Indicates if cookies should be serialized.
/*
/* @var bool
 */
protected static $serialize = true;

in Http/Middleware/EncryptCookies.php fixed it for me.

eaguad1337 commented 6 years ago

If you changed your users id type publish passport migrations and update them with the new column type. #806

shehi commented 6 years ago

Thanks @a1tem , adding serialize = true fixed it for me.

littpi-zz commented 6 years ago

Hello. I have faced the problem too and I will try to solve with @a1tem 's solution tonight.

However, there is a news about Malicious on serialize() and unserialize(). Is it connected to the function on this?

mfgabriel92 commented 6 years ago

@a1tem 's solution for me didn't work. Laravel 5.6.33, Passport 7.0. I am trying to access via REST API software.

muhci commented 6 years ago

Hello,

If anyone is getting unauthenticated error when accessing API via JavaScript (axios, jQuery etc.) using laravel_token cookie then here is the solution.

Normally, JWT::decode method throws an exception which says 'Malformed UTF-8 Characters' when the static variable $unserializesCookies is false (default value).

Passport class has a static method called 'withCookieSerialization'.

So, in boot method of your AuthServiceProvider class you should call Passport::withCookieSerialization();

Regards.

amarebglobal commented 5 years ago

Hello, i am facing same problem here i'm doing to access user profile details after logout and there is expired authrization token but hit the api i'm getting html response and im not handling error where i can send customize error and message to android developer.

RipleWare commented 5 years ago

I'm getting the same problem with Laravel 5.6. Tried the $serialize = true option but that made no difference. I can pass the token in the URL ?token=<token> and that works fine, but if I try and pass it as a Bearer in the authorization header I continually get token required errors. I have tried moving my Laravel app to apache but that also made no difference. I have also modified the .htaccess file in my public directory and again nothing. I'm out of ideas.

KerryJones commented 5 years ago

Hello,

If anyone is getting unauthenticated error when accessing API via JavaScript (axios, jQuery etc.) using laravel_token cookie then here is the solution.

Normally, JWT::decode method throws an exception which says 'Malformed UTF-8 Characters' when the static variable $unserializesCookies is false (default value).

Passport class has a static method called 'withCookieSerialization'.

So, in boot method of your AuthServiceProvider class you should call Passport::withCookieSerialization();

Regards.

Unauthenticated or Unauthorized?

danyal14 commented 5 years ago

Hi I went through the whole post, I am facing same issue with following config "laravel/framework": "5.6.30", "laravel/passport": "7.0",

@a1tem I followed what you suggested, no success same response "Unauthenticated" my post https://stackoverflow.com/questions/52496543/laravel-5-6-passport-unauthenticated

rboughani commented 5 years ago

public function __construct() { $this->middleware('auth'); }

/**

ahmadmrj commented 5 years ago

Setting serialize=true worked for me. thanks @a1tem

ghost commented 5 years ago

Refering to the update docs setting serialize = true is not the best way.

https://laravel.com/docs/5.6/upgrade

You should instead use Passport with the withoutCookieSerialization() flag in AuthServiceProvider.

driesvints commented 5 years ago

Hey everyone,

Like @a1tem said, there have been some changes to cookie serialization so make sure to clear caches and refresh your cookies to solve some of the problems.

Like @muhci said, there is support for disabling cookie serialization but it's undocumented. I'll send in a PR to the docs to document this config.

As for the server config issues with Apache & nginx: we cannot offer guidelines for every single situation. There have been issues about several situations int he past, please refer to the issue tracker for them for solutions or use one of the support channels for questions about them (Laracasts, Laravel.io, etc).

Please always make sure you're using the latest Laravel and Passport version.

As there have been much different issues in this thread, it's difficult to manage all of them here in one place. If you're experiencing a bug with something, feel free to first search if your problem has been reported before in the issue tracker and if not to create a separate issue with a detailed description of your problem.

Please refer to above answers to see if anything solves your problem.

Thanks for everyone who responded to this thread with answers and offering help. Much appreciated!

bulgariamitko commented 5 years ago

i am still getting the same error using Insomnia app to get the user data with 'Accept': 'application/json' and 'Authorization': 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciO....' (and this token was just created seconds ago) what i tried so far:

none of those worked for me

bulgariamitko commented 5 years ago

It turn out i am getting this error, because i am not using Postman the right way, lol! it should be with the Auth tab and i have been trying to do it with the Form tab.... silly mistake!

o-ayoub commented 5 years ago

did any one has fixed this issue ?

ezp127 commented 5 years ago

Here's my setup:

Maybe some of the steps can help someone.. Please let me know if I did something wrong/insecure, I'm learning too.

I have two separate projects in my Homestead

I did the following steps:

I will not describe here what is already in the Laravel docs (Passport), just highlight the minimum I had to do to get authentication working, so please take a look at the docs for details.

api.company.test

Create a dedicated LoginController (you can make it different according to your needs)

routes/api.php

Route::post('login', '\App\Http\Controllers\Auth\LoginController');

LoginController.php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Features\UserModel;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
    public function __invoke(Request $request)
    {
        if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){ 
            $user = Auth::user(); 
            $success['token'] =  $user->createToken('access_token')->accessToken; 
            return response()->json([
                'data' => $success
            ], 200);
        } else { 
            return response()->json([
                'data' => 'API: Unauthorized Access'
            ], 401);
        } 
    }
}

app.company.test

/src/main.js

window.axios = require('axios')
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'
window.axios.defaults.headers.common['Content-Type'] = 'application/json'
window.axios.defaults.baseURL = (process.env.NODE_ENV !== 'production') ? 'http://api.company.test/api/' : 'http://api.company.test/api/'
Vue.prototype.$http = window.axios

Create a vue route for your login page and make a login form. Here's the script part of the Login.vue component

/src/views/Login.vue

<template></template>

<script>
export default {
    data() {
        return {
            form: {
                email: 'user@example.org',
                password: 'secret',
                remember: false
            }
        }
    },
    methods: {
        login() {
            this.$http.post('login', this.form)
                .then((response) => {

                    let token = response.data.data.token

                    // Store the token in Vuex or Cookie.. or another secure location
                    // so you can retrieve it and attach again to the axios default headers 
                    // in case user hit F5 or close the browser.
                    // this.saveTheToken(token) 

                    this.$http.defaults.headers.common['Authorization'] = 'Bearer ' + token
                    this.$router.push('/dashboard')
                })
                .catch((err) => {
                    // email or password incorrect
                    console.error(err)
                })
        }
    }
}
<script>

/src/views/Dashboard.vue

<template></template>

<script>
export default {
    created() {

        // api.company.test/api/dashboard (protected route with auth:api middleware)
        // This request should have the Authorization header with the Baerer token attached to it

        this.$http.get('dashboard')
            .then(response => {
                // Should work
                console.log(response)
            })
    }
}
<script>

Please forgive any grammar error (English is not my native language)

samier commented 5 years ago

@ezp127 do you find solution for above problem?