1
votes

I am making a mobile application with a laravel API, and I saw that since Laravel 5.3(?) they added something called "Passport" which handles OAuth2/verification for an application, so I thought I would give that a try. I followed several different explanations for how to get it working after I completed the setup using the Laravel Passport documentation (https://laravel.com/docs/5.4/passport). Right now this is the code for what I've come up with based off other tutorials/ SO articles

1.) Controller for creating the user/oAuth2 client

class OAuthController extends Controller
{
    public function registerUser(Request $request){

    $email = $request->email;
    $password = $request->password;
    $name = $request->name;
    $user = User::create([
        'name' => $name,
        'email' => $email,
        'password' => bcrypt($password)
    ]);

    $oAuthClient = new OAuthClient();
    $oAuthClient->user_id = $user->id;
    $oAuthClient->id = $user->email;
    $oAuthClient->name = $user->name;
    $oAuthClient->secret = base64_encode(hash_hmac('sha256',$password, 'secret', true));
    $oAuthClient->password_client=1;
    $oAuthClient->redirect = '';
    $oAuthClient->personal_access_client = 0;
    $oAuthClient->revoked = 0;
    $oAuthClient->save();

    return response()->json(['message', 'User successfully created']);
}
}

2.) The model I made to reference the oauth_clients table

use Illuminate\Database\Eloquent\Model;

class OAuthClient extends Model
{
    protected $table = 'oauth_clients';
} 

3.) I changed the oauth_clients table primarykey from incrementing integer to the users email. I was basically just following this SO article Laravel Passport Password Grant Tokens: own mobile app

4.) Once I have created the user/oauth_client, retrieve the token through POSTMAN w/ post request to oauth/token with parameters

enter image description here

The thing is, this feels really wrong to me. the oauth_clients has a user_id column on it, so it really leads me to believe when attempting to get the oauth_client token that I should be able to do some post request where it will take the user and then get the associated oauth_client, right?

In my mind what makes sense for how I should be able to use Passport for user authentication for my mobile app is as follows: 1.) Register new user

2.) When registering user, create oauth_client for that user

3.) On login, once user email/pw is verified, look for oauth_client and then retrieve the oath_client token

4.) Use oauth_client token on any requests to API going forward to verified authenticated user.

Is this the right way to think of it?? I'm sure it's apparent, but this process has me confused so any guidance will be greatly appreciated.

1

1 Answers

2
votes

ok so, incase anyone is interested or has any future suggestions, Here is what I did in the end to get this working.

I created a new route for mobile register,

    Route::post('/mobile_register', 'Auth\RegisterController@mobileRegister');

Then I basically just copied the actual register method but added a new function to create a new oauth_client based off of the successful user register information

 /**
 * Register a new user through the mobile application. Send back the oauth_client ID which will be used
 * to retrieve the oauth token
 *
 * @param Request $request
 * @return \Illuminate\Http\JsonResponse
 */
public function mobileRegister(Request $request){

    $this->validator($request->all())->validate();

    $password = $request->password;
    event(new Registered($user = $this->create($request->all())));

    $oAuthClient = $this->registerOAuthClient($user, $password);

    return response()->json(['message' => 'user created successfully', 'client_id' => $oAuthClient->id]);
}

/**
 * Create the associated oauth_client for this user.
 *
 * @param User $user
 * @param $password
 * @return \Illuminate\Http\JsonResponse|OAuthClient
 */
public function registerOAuthClient(User $user, $password){

    $oAuthClient = new OAuthClient();
    $oAuthClient->user_id = $user->id;
    $oAuthClient->name = $user->name;
    $oAuthClient->secret = base64_encode(hash_hmac('sha256',{{whatever you want your secret to be based off of}}, 'secret', true));
    $oAuthClient->password_client=1;
    $oAuthClient->redirect = '';
    $oAuthClient->personal_access_client = 0;
    $oAuthClient->revoked = 0;
    if(!$oAuthClient->save())
        return response()->json(['error' => 'Unable to create oAuthClient! User will need one made to access website']);

    return $oAuthClient;
}

So now the new oAuthClient ID will be sent back to the mobile app, and then INSIDE your mobile application you can create the 'client_secret' which needs to be sent off to get the oauth token, and you can use the client_id sent back from the API as the 'client_id' in your oauth/token post request as well. Then you will send off your second post request to retrieve the actual oauth token for the user.

I felt this was best because then I am not required to store any sensitive user information on the application, and even though I am sending back the client id, unless some nefarious party knows what you are going to be using for the 'client_secret' as well, they can't gain access to your oauth client to retrieve a token.. and they won't know your user either so they can't determine your oauth client from your user. I also liked this solution because I am still verifying the user exists, & the pw is correct before doing the second verification of the oauth_client information.

Disclaimer::this is my first attempt at using Passport or really doing any sort of authentication, so it's certainly possible there's issues with this. If you see any, please comment or post to let me know! I want to make sure this is as good as possible so I will greatly appreciate it!