Using Sentry 2, what is the difference between authenticate() and login()? - laravel-4

Using Cartalys Sentry 2, and I can't seem to find any documentation on the difference between the authenticate() and login() methods, nor when to use one versus the other. Any guidance appreciated.

The difference is that authenticate will receive an array of credentials:
// Login credentials
$credentials = array(
'email' => 'john.doe#example.com',
'password' => 'password',
);
// Authenticate the user
$user = Sentry::authenticate($credentials, false);
And the login method receives an $user object
// Find the user using the user id
$user = Sentry::findUserById(1);
// Log the user in
Sentry::login($user, false);

Related

Authorization code grant with Socialite setup

I'm trying to implement an Authorization code grant with Socialite. I'm able successfully to receive users in the callback, but struggling to set up the other part of auth. I've created the personal passport client and received the client ID & Secret in oauth_clients. Whenever I use the createToken() I am able to see oauth_access_tokens these tokens with the name of PKCE(which contains the same name as in oauth_client). The $code is taken from the query in the callback, however, the $response in the very end is null, any idea why?
public function callbackGoogle()
{
// Receive the user credentials from social
$googleUser = Socialite::driver('google')->stateless()->user();
// Get the user by email
$user = User::where('email', $googleUser->email)->first();
// Create token
$user->createToken('PKCE')->accessToken;
// Get query parameter code from callback
$code = request()->query()['code'];
// Get client data
$client = DB::table('oauth_clients')->where('name', 'PKCE')->first();
$response = Http::asForm()->post('http://localhost:5000/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => $client->id,
'client_secret' => $client->secret,
'code' => urldecode($code),
'redirect_uri' => $client->redirect,
]);
// // Receiving null
dd($response->json());
}
You are trying to exchange an access token from google with your own application.
This does not make sense.
With this line:
$googleUser = Socialite::driver('google')->stateless()->user();
You have already exchanged the code from the URL with a token from google.
If you want to get an API token for your API, you already did this with
$user->createToken('PKCE')->accessToken;
You could use
$token = $user->createToken('PKCE')->accessToken;

Why Auth::check() returns true after logout ? Passport

So I made Authentication using passport, everything worked fine until I logged user out. My paths are protected via auth:api guard so after logging out I can't access any functions, however my frontend is rendered via react based on Auth:check() value and it stays true after logging out. Therefore I am able to get into admin dashboard without any permissions, which is a bug and I can't find a solution to fix it.
This is my log out function:
public function logout()
{
if (Auth::check()) {
DB::table('oauth_access_tokens')
->where('user_id', Auth::user()->id)
->update([
'revoked' => true
]);
return response(['check' => Auth::check()]); // I get true after logging out
}
return response(['check' => Auth::check()]);
}
This is my login and register functions:
public function register(Request $request){
$validatedData = $request->validate([
'name' => 'required|max:55|unique:users',
'password' => 'required'
]);
$validatedData['password'] = bcrypt($request->password);
$user = User::create($validatedData);
$accessToken = $user->createToken('authToken')->accessToken;
return response()
}
public function login(Request $request)
{
$loginData = $request->validate([
'name' => 'required',
'password' => 'required'
]);
$a = auth()->attempt($loginData, true);
if(!$a) {
return response(['message'=>'Invalid credentials');
}
$accessToken = auth()->user()->createToken('authToken')->accessToken;
return response()->json($accessToken);
}
What have I missed?
The reason that Auth::check() returns true is the user is set on the auth service. You are only revoking the access token, meaning that the user will be logged out from the next request.
You can solve this one of two ways
1) Assume that the any call to the logout route will result in the user being logged out, irrespective of the logic performed. For example, you could make the call and then clear the access token in your frontend (or perform whatever other logout logic).
2) You can call Auth::logout() in your code, which will set the current user on the authentication service to null resulting in Auth::check() returning false.

How to enable offline access to customer data in google adwords api php

Google Adwords API (PHP Client)
I am trying to get a user to authorize once on my website to be able to get his data for analytical purposes. But I can not figure out a way to do it with the documentation it is quite complex.
Do I need to add them to my mcc to be able to do this or is there another way using something like https://developers.google.com/identity/protocols/OAuth2WebServer
You will have to connect the user via oauth token with offline access activated, so that the request returns a refresh token, that you can use to programmatically access the connection, even if the user is not logged into you application:
$client->setApprovalPrompt('force');
$client->setAccessType('offline');
As explained here https://developers.google.com/adwords/api/docs/guides/authentication you can use the oauth playground from groogle to test the api and see what you need.
Additionally here is an example for the client connection method (partially Laravel specific code, but should be good enough to explain the procedure):
function googleIntegrationClient($refresh=false)
{
$client = new \Google_Client();
$client->setClientId(env('GOOGLE_OAUTH_CLIENT_ID'));
$client->setClientSecret(env('GOOGLE_OAUTH_CLIENT_SECRET'));
$client->setRedirectUri(env('GOOGLE_OAUTH_REDIRECT_URI'));
$client->setApplicationName('App Google Integration');
$client->addScope("profile");
$client->addScope("email");
$client->addScope("https://www.googleapis.com/auth/adwords");
//make sure there is a refresh token in the request for offline access.
$client->setApprovalPrompt('force');
$client->setAccessType('offline');
if($refresh)
{
//get currently logged in user
$user = \Auth::user();
//set token from user data
$client->setAccessToken($user->settings["integration"]["google"]['token_data']);
//check if token is valid
if($client->isAccessTokenExpired())
{
//as token is invalid set refresh token
$token_data = json_decode($user->settings["integration"]["google"]['token_data']);
$client->refreshToken($token_data->refresh_token);
//save new token data
$modify_settings = $user->settings;
$modify_settings["integration"]["google"]["token_data"] = $client->getAccessToken();
$user->settings = $modify_settings;
$user->save();
}
}
return $client;
}
You can use this method then in your oauth connecting routine:
//route for redirecting to google oauth
public function redirectToProvider()
{
$user = \Auth::User();
$client = googleIntegrationClient();
$auth_url = $client->createAuthUrl();
return \Redirect::to(filter_var($auth_url, FILTER_SANITIZE_URL));
}
//callback route to handle the provided data from google oauth
public function handleProviderCallback(Request $request)
{
$user = \Auth::User();
$client = googleIntegrationClient();
$data = $request->all();
if (isset($data['code']))
{
try {
$client->authenticate($data['code']);
$token = $client->getAccessToken();
} catch (Exception $e) {
$user->settings = array(
"integration" => array(
"google" => array(
'active' => false,
)));
$user->save();
}
if($token)
{
$google_oauth = new \Google_Service_Oauth2($client);
$user->settings = array(
"integration" => array(
"google" => array(
'active' => true,
'token_data' => $token,
'id' => $google_oauth->userinfo->get()->id,
'avatar' => $google_oauth->userinfo->get()->picture,
'email' => $google_oauth->userinfo->get()->email,
'name' => $google_oauth->userinfo->get()->name,
)));
$user->save();
}
}
}
Good luck!

Cartalyst Sentinel Laravel - How do you create roles?

Im new to Cartalyst Sentinel and this concept of ACL. I've managed to create a user, perform activation and login and logout.
I'd like to take my learning to the next level. I would like 2 types of Users on this laravel app. 1 is Administrator another is Subscriber. I'm assuming my account creation method should by default create the user a subscriber.
public function postCreate() {
/* Validation */
$validation = Validator::make(Input::all(), [
'email' => 'required|email|max:50|unique:users',
'username' => 'required|min:3|max:20|unique:users',
'password' => 'required|min:6',
'password_repeat' => 'required|same:password',
]);
if ($validation->fails()) {
return Redirect('login')->withErrors($validation)->withInput();
} else {
$credentials = Input::all();
$user = Sentinel::register($credentials);
$activation = Activation::create($user);
$activation_code = $activation->code;
if ($user) {
Mail::send('emails.auth.activate', ['link' => URL::route('account-activate', [$user->id, $activation_code]), 'username' => $user->username], function($message) use ($user) {
$message->to($user->email, $user->username)->subject('Activate your account');
});
return Redirect::route('home')->with('global', 'Thank you for registering! We have sent you an email to activate your account');
}
}
}
Do i alter the code like so
$user = Sentinel::register($credentials);
$user = Sentinel::findById(1);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
The thing is i have not even created any roles to begin with. Where do we write that functionality? Right now i have the following Controllers
AccountController - handles activation
AuthController - handles login/logout
RegistrationController - handles registration of user
RolesController - i've not written anything inside here yet. Im a bit lost.
Please guide me. Any help is greatly appreciated.
You do not need to do a search for your user if you already registered them, the register method returns the user.
You can do the following to attach a role to a user:
$user = Sentinel::register($credentials);
$role = Sentinel::findRoleByName('Subscribers');
$role->users()->attach($user);
// OR
$user->roles()->attach($role);
you have both a user and a role object and they have a many to many relation so it doesn't matter which one you use.
You will need to create a db seeder or a method to create your permissions. But to create your Subscribers Role you will need to do the following:
Sentinel::getRoleRepository()->createModel()->create([
'name' => 'Subscribers',
'slug' => 'subscribers',
'permissions' => [
'user.view' => true,
'user.delete' => false,
// any other permissions you want your Subscribers to have
]
]);
A similar call can build your Administrator roles as well.
Your Roles Model and Controller are already built for you, you just need to access them through Sentinel, which you already have Sentinel::findRoleByName('Subscribers'); call.
Cartalyst has some pretty decent documentation about setting up roles and permissions for your users:
https://cartalyst.com/manual/sentinel#roles
https://cartalyst.com/manual/sentinel#permissions
It's just a matter of figuring out what you want each role to do or not do.
Also, you can set specific permissions per user to override the role permissions.

Laravel - Oauth password grant

I find it difficult to wrap my head around the password grant authentication process.
What I'm trying to achieve: A mobile device sends the username and the password of a registered user to the API and gets the access token as a response in JSON form.
What I've achieved so far: The API receives the user credentials (username and password) and authenticates the user using Laravel's built-in Auth authentication system.
I know that at this point I should proceed to Oauth authentication. Once the credentials pass the Auth step, I have the user's username, password (specified in the users table) and I can get the client_id and client_secret from the oauth_clients table, but I'm not sure how to accomplish the rest. Do I need to make another POST request? If yes, then how do I do it from the controller?
I am actually implementing this right now. Let me show you some code.
This is my part of my login function:
// this does the process for getting the access token
$oauth = AuthorizationServer::performAccessTokenFlow();
// some hacks
$oauth = (array) $oauth;
// more hacks
$oauth = json_decode($oauth["\0*\0data"], true);
// checks if a token was actually generated
if(!in_array('bearer', $oauth))
{
// returns what was generated if the token is missing
return Responser::error(400, $oauth);
}
You would have to post additional data on your login other than the username and password of the user.
So your post request will contain:
username=the_username
password=the_password
grant_type=password
client_id=the_client_id
client_secret=the_client_secret
note that grant_type=password is constant.
Now you have to check the configurations of the package too found at app/config/packages/lucadegasperi/oauth2-server-laravel/oauth2.php:
You should have the following code:
'password' => array(
'class' => 'League\OAuth2\Server\Grant\Password',
'access_token_ttl' => 604800,
'callback' => function($username, $password){
$credentials = array(
// change this to username if username is the field on your database
'email' => $username,
'password' => $password,
);
$valid = Auth::validate($credentials);
if (!$valid) {
return false;
}
return Auth::getProvider()->retrieveByCredentials($credentials)->id;
}
),
And you are done.
update
the code above that generates the token is inside this function:
// allow user to login with username or email and password
$user_pass = array('username' => $username, 'password' => $password);
$email_pass = array('email' => $username, 'password' => $password);
// check if input is email and use $email_pass combination or else use $user_pass combination
$login = ($isEmail->passes() ? $email_pass : $user_pass);
// try to authenticate username & password
if (Auth::attempt($login))
{
// now you are authenticated here
// get the client id and secret from the database
// maybe use curl or some hacks
// login stuff and token generation
}
This is a bit of an old post, but if you are looking to do this without having multiple post requests, you could always just do something like:
//Get Oauth creds
$apiCreds = OauthClient::where('email', Input::get('email'))->first();
//Provide additional post data for password grant
Input::merge([
'grant_type' => 'password',
'client_id' => $apiCreds->id,
'client_secret' => $apiCreds->secret,
'username' => Input::get('email'),
'password' => Input::get('password'),
'scope' => 'all'
]);
//Login
return AuthorizationServer::performAccessTokenFlow();

Resources