57

Is it safe to use the remember_token in the users table for authenticating the user into the application?

What is the purpose of this token? Currently, I'm using it in forms to check whether the user is logged in - if the token is not present, I show the login screen. Each time the user logs out, this token is regenerated.

Jan Żankowski
  • 8,690
  • 7
  • 38
  • 52
Onion
  • 1,714
  • 1
  • 23
  • 42

5 Answers5

93

No. It's not supposed to be used to authenticate. It's used by the framework to help against Remember Me cookie hijacking. The value is refreshed upon login and logout. If a cookie is hijacked by a malicious person, logging out makes the hijacked cookie useless since it doesn't match anymore.

Refer to this documentation:

https://laravel.com/docs/4.2/upgrade#upgrade-4.1.29

jgawrych
  • 3,322
  • 1
  • 28
  • 38
sidneydobber
  • 2,790
  • 1
  • 23
  • 32
  • How should I then implement an authentication system using a token? I need this to get the app running. – Onion Apr 24 '14 at 07:34
  • Tokens are used to reset credentials, like password reminders. For authentication you should use the Auth:: class. – sidneydobber Apr 24 '14 at 07:38
  • I understand that, but I'm developing an API for mobile devices, therefore I need to authenticate the device using a token. – Onion Apr 24 '14 at 07:40
  • A I get it, in an OAuth2.0 kind of way? I have been working on this as well, but this is pretty hard to implement. I will give you some links. – sidneydobber Apr 24 '14 at 07:42
  • This is basic auth authentication and not save to use, even when using HTTPS (SSL) it's not recomended. – sidneydobber Apr 24 '14 at 07:47
  • I would recommend using OAuth2.0 https://github.com/lucadegasperi/oauth2-server-laravel! It's not easy to implement, but this is the most secure way at the moment. You should be really careful with this stuff it also depends on how sensitive the information is that your API is serving. – sidneydobber Apr 24 '14 at 07:53
  • The token can be intercepted by a malicious person and used for API calls in behalve of the original user. – sidneydobber Apr 24 '14 at 07:55
  • 1
    http://security.stackexchange.com/questions/988/is-basic-auth-secure-if-done-over-https – sidneydobber Apr 24 '14 at 07:57
  • One question: I'm not using FB, Twitter or any other accounts in my application. Which grant should I use if I want to authenticate a user using an email and a password in my users table? – Onion Apr 24 '14 at 08:04
  • This should work, I succesfully implemented this grant. It is not to hard to setup. http://oauthlib.readthedocs.org/en/latest/oauth2/grants/password.html – sidneydobber Apr 24 '14 at 08:08
  • A friendly overview: http://oauthlib.readthedocs.org/en/latest/oauth2/grants/grants.html and the official overview: http://tools.ietf.org/html/rfc6749 hope this will help you. – sidneydobber Apr 24 '14 at 08:11
  • 1
    OAuth is simply for safely establishing cross origin authentication. Good luck and beware, do not take this lightly since you might open up your whole database for the public and not be aware of this! I spend days of reading and sandboxing pet projects and I'm still a noob! :) – sidneydobber Apr 24 '14 at 08:13
  • Thanks for the help. I still find it difficult to understand how to use oauth2 in my application - specifically the password grant. Edit: I guess I'm starting to get the hang of it. – Onion Apr 24 '14 at 08:14
  • 1
    1. Register the user with the API (database that OAuth uses). 2. The user logs in to the app, the app sends a request for a token and gets it because the user is valid. 3. The user can do requests using the token to validate. In a nutshell. :) – sidneydobber Apr 24 '14 at 08:19
  • I'm currently setting up a test form that I will use to authenticate the user. I've added the `grant_type` parameter (with a value of `password`), but the app requests a `client_id` as well. What should I use for `client_id` and `client_secret`? – Onion Apr 24 '14 at 08:21
  • client_id is the username and client_secret is an extra value that can be set by the user when registering or generated by your app these are both set on the API database that OAuth uses. – sidneydobber Apr 24 '14 at 08:24
  • Here's what I've found: `Every registered OAuth application is assigned a unique Client ID and Client Secret.` Does this mean that along with the username and password I need to send two extra parameters - `client_id` and `client_secret` - both obtained after registering my application? – Onion Apr 24 '14 at 08:25
  • 1
    I always use postman REST client to do my testing. https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm?hl=en – sidneydobber Apr 24 '14 at 08:26
  • There is an `Authorization callback URL` field in the oauth application registration form. What exactly should be input here? – Onion Apr 24 '14 at 08:30
  • The callback url is not mandatory, this is what happens when you login using your Twitter account, Twitnerd is a good example. You get redirected to the url you came from after successfully logging in, in that case the Twitnerd website. But this is not what you are trying to do! – sidneydobber Apr 24 '14 at 08:39
  • But I get the following error: 'invalid_client'. If I don't put client_id and client_secret in the form I also get errors, which tell me that the parameters are malformed. How do I solve this? – Onion Apr 24 '14 at 08:45
  • Yes you should put them in the form, these are used to authenticate the request, they should match a user and secret in the OAuth database. – sidneydobber Apr 24 '14 at 08:58
  • How do I get the client id and secret then? Generate it when the user registers? – Onion Apr 24 '14 at 08:59
  • 1
    I created a chatroom to continue the conversation in the right place. http://chat.stackoverflow.com/rooms/51330/implement-oauth2-0-password-flow – sidneydobber Apr 24 '14 at 09:03
  • when create new user can I put it empy? – Chhorn Elit Dec 19 '18 at 11:57
  • You don’t have to do anything in get’s done for you. For testing while developing you can delete them. – sidneydobber Dec 19 '18 at 11:59
12

I had to add the remember_token to my users table migration in order for Auth::logout() to work properly.

Added remember_token to my migrations as such.

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
        Schema::create('users', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('lname', 32);
            $table->string('fname', 32);
            $table->string('username', 32);
            $table->string('email', 320);
            $table->string('remember_token', 100);
            $table->string('password', 64);

            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
        Schema::drop('users');

    }

}

From the command-line you the have to drop the users table, then migrate/seed.

whoan
  • 8,143
  • 4
  • 39
  • 48
Cyril T
  • 190
  • 7
  • 3
    Just wanted to point out a minor change - according to the [Laravel upgrade guide][http://laravel.com/docs/upgrade#upgrade-4.1.26] the remember_token should be 100 not 64 - so `$table->string('remember_token', 100);` – SnapShot Jul 08 '14 at 22:02
  • And ->nullable() "you should verify that your users (or equivalent) table contains a nullable, string remember_token column of 100 characters" – markdwhite Sep 07 '16 at 06:45
5

Even if this an old question, I wanted to present an option not use the token if you don't need it (e.g. have no remember me option on your site).

Instead of adding a dummy column to your users table you can just prevent Auth::logout() from setting it.

Just add this to your User model (works as of Laravel 5.6):

public function save(array $options = array()) {
    if(isset($this->remember_token))
        unset($this->remember_token);

    return parent::save($options);
}

This removes the 'remember_token' column just before the model gets saved and thus preventing an error to be risen because of the non-existant column.

LinusCDE
  • 141
  • 3
  • 8
0

Laravel provides a CSRF token in a hidden input it automatically adds and validates whenever a form is submitted, whether you're logged in or not. If you're using their Form builder, this is happening without you even needing to check on it.

You should check if the user is logged in on submission using the Auth facade.

DanielM
  • 6,380
  • 2
  • 38
  • 57
0

To solve the problem of rememberToken in Logout Add functions in Auth/LoginController:

function get_guard(){
        if(Auth::guard('web')->check()){
            return "web";
        }
        elseif(Auth::guard('manager')->check()){
            return "manager";
        }
        elseif(Auth::guard('client')->check()){
            return "client";
        }
        return "web";
    }

    public function logout(){
        $guard = $this->get_guard();
        switch ($guard) {
            case 'admin': Auth::guard('admin')->logout(); break;
            case 'web' : Auth::guard('web')->logout(); break;
            default : Auth::guard('web')->logout(); break;
        }
        return redirect()->guest(route("login"));
    }