I have a Laravel application that uses Passport authentication.
Login
public function authenticate(Request $request)
{
$params = [
'grant_type' => 'password',
'client_id' => 1,
'client_secret' => "secret",
'username' => request('username'),
'password' => request('password'),
'active' => 1,
'scope' => '*'
];
$request->request->add($params);
// verify the credentials and create a token for the user
$proxy = Request::create('oauth/token', 'POST');
return Route::dispatch($proxy);
}
I have settled the expiration on AuthServiceProvider:
Passport::routes(function ($router) {
$router->forAccessTokens();
});
Passport::tokensExpireIn(now()->addMinute(1));
Passport::refreshTokensExpireIn(now()->addDays(30));
It works but after 1 minute the token expires. I want a different expiration date for token depending on where I'm trying to make login because I have a website, desktop app and an Android app.
For example:
web app: 8 hours
desktop app: 1 Year
android app: 5 months
I was thinking send me from where I'm trying to make the login, but is that a good way? Are there any other possible ways to do it?
For now I have tried this:
-) deleted From AuthServiceProvider:
Passport::tokensExpireIn(now()->addMinute(1));
And added in Login function:
if (request('from') == 'something') {
Passport::tokensExpireIn(now()->addYears(1));
} else {
Passport::tokensExpireIn(now()->addHours(8));
}
$proxy = Request::create('oauth/token', 'POST');
You can get help from below link please find
For getting user agent detail and apply condition base on agent
for example you can use code like below
if ( Agent::isDesktop() ) {
Passport::tokensExpireIn(now()->addYears(1));
} else if(Agent::isMobile()){
Passport::tokensExpireIn(now()->addMonth(5));
}else{
Passport::tokensExpireIn(now()->addHours(8));
}
Related
i want to access token made with laravel passport has a refresh or an "extra time" eacth time user makes a request, but i really dont understand laravel documentation and each forum i've seen sends me there https://laravel.com/docs/5.8/passport#refreshing-tokens i really dont understand witch parameters should i user, or where to get it.
So i decided to look for expiration time manually, Passport create 5 tables oauth accesToken, clients, personal_access_clients refresh_token and refresh_token, oauth_access_token has a column with expired_at field, so i thought if i change the time i'll get a longer token but i was wrong.
When i create token in boot method i set time
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::personalAccessTokensExpireIn(now()->addMinutes(1));
Passport::refreshTokensExpireIn(now()->addMinutes(1));
}
this is working fine, but in login method
$tokenResult = $user->createToken('Token Acceso Personal');
$token = $tokenResult->token;
if ($request->remember_me) {
$token->expires_at = Carbon::now()->addWeeks(1);
}
//this line it supose to set the expired time
$token->expires_at = Carbon::now()->addWeeks(1);
//------------------
$userLogin->token = $tokenResult->accessToken;
$userLogin->save();
$token->save();
$profile = $people->where('user_id', $userLogin->id)->first();
$profile_name = $profile2->where('id', $profile->profile_id)->first();
return response()->json([
'access_token' => $tokenResult->accessToken,
'token_type' => 'Bearer',
'expires_at' => Carbon::parse($tokenResult->token->expires_at)->toDateTimeString(),
'user_id' => $userLogin->id,
'profile_id' => $profile->profile_id,
'profile_name' => $profile_name->name,
'companies' => $companies
]);
when i set the time here it saves in DB but it doesnt work like expiration time, in other words, the expiration time in DB isn't working or it's not using it, so i'm curious if there is a place where should i look in order to find the expiration time setted in boot method or how could i set a longer time in token
The property $token->expires_at is just a reference from the Database, what you can do is:
if ($request->remember_me) {
Passport::personalAccessTokensExpireIn(Carbon::now()->addWeek());
}
I am pulling User Information from an external site with external API. I have completed the user login route on the Laravel and I get the data from the controller file. There is no problem in terms of pulling and displaying data from an external user API link.
How to do token and session operation like regular Laravel user to the user logged in with external API without the database. Note that I can use the same token part of the user API token available
In addition, I don't want to transfer the information by assigning session between the controller each time the user was login. How do I assign tokens in all transactions after user login?
It comes to these controls via post method from login screen
public function loginData(Request $request)
{
$password = $request->password;
$email = $request->email;
$apiman = "Bearer {$this->accesstokenApi()}";
$client = new Client();
$response = $client->post('https://testapi.com/api/v3/Profile', [
'headers' =>
[
'cache-control' => 'no-cache',
'authorization' => $apiman,
'content-type' => 'application/json'
],
'json' =>
[
'Email' => $email,
'Password' => $password
],
]);
$data = json_decode((string) $response->getBody(), true);
if ($data['ResponseType']=="Ok") {
session()->put('token', $data);
return redirect('/user-detail');
} else {
return response()->json([
'success' => false,
'message' => 'Invalid Email or Password',
], 401);
}
}
User logged in OK . After that, what token should the machine give, or where can the session be given to that user in one place? Besides, if the user is logged in, how do I get him to see the home page instead of showing the login form again, just like in Laravel login processes ?
Maybe you can create new middleware that will check if there is a token in the session
Here is the example that you can use and adapt it based on your needs.
namespace App\Http\Middleware;
use Closure;
class Myauth
{
public function handle($request, Closure $next, $guard = null)
{
if(session()->has('token')) {
return $next($request);
} else {
return response('Unauthorized.', 401);
//OR return redirect()->guest('/');
}
}
}
I am trying to add social authentication to a Laravel 5.8 API project using socialite.
When trying to handle a social provide callback, the ArgumentCountError is thrown here
Too few arguments to function App\Http\Controllers\SocialAuthController::handleProviderCallback(), 0 passed and exactly 1 expected
The error is referring to the very first line of this code block
public function handleProviderCallback($provider)
{
// retrieve social user info
$socialUser = Socialite::driver($provider)->stateless()->user();
// check if social user provider record is stored
$userSocialAccount = SocialAccount::where('provider_id', $socialUser->id)->where('provider_name', $provider)->first();
if ($userSocialAccount) {
// retrieve the user from users store
$user = User::find($userSocialAccount->user_id);
// assign access token to user
$token = $user->createToken('Pramopro')->accessToken;
// return access token & user data
return response()->json([
'token' => $token,
'user' => (new UserResource($user))
]);
} else {
// store the new user record
$user = User::create([
'name' => $socialUser->name,
'username' => $socialUser->email,
'email_verified_at' => now()
]);
...
// assign passport token to user
$token = $user->createToken('******')->accessToken;
// return response
return response()->json(['token' => $token]);
}
}
Below is how I have set up other code. Frist in env I added
GOOGLE_CLIENT_ID=******
GOOGLE_CLIENT_SECRET=*******
GOOGLE_CALLBACK_URL=https://staging.appdomain.com/api/v1/user
Then modified web.php
Auth::routes(['verify' => true]);
Route::get('/auth/{provider}', 'SocialAuthController#redirectToProvider');
Route::get('/auth/{provider}/callback', 'SocialAuthController#handleProviderCallback');
Lastly in the google app, I added the uri path where users will be redirected to after successful authentication
https://staging.appdomain.com/api/v1/user
How do I fix this?
The callback uri that user should be redirected to after successful authentication was apparently not being cached. So running php artisan route:cache fixed it.
I'm currently trying to implement a way to synchronize my PHP App calendar with the Outlook calendar of my clients, using Azure API.
I use OAuth2 and the custom Microsoft provider by Steven Maguire.
I currently run in an issue where I get an error in my response :
{"error":"unsupported_grant_type","error_description":"The provided value for the input parameter 'grant_type' is not valid. Expected values are the following: 'authorization_code', 'refresh_token'."}
I'm having trouble understanding why the grant_type password is not supported, even though it says on the documentation of Azure that it is.
The request looks like this :
client_id=44bef79b-**********************&client_secret=H****************&redirect_uri=https%3A%2F%2F192.168.1.123%2Fmapeyral%2Fcalendarsync.php&grant_type=password&username=******************&password=***********&scope=openid%20profile%20offline_access%20Calendars.ReadWrite
The Authorize url used is : https://login.live.com/oauth20_token.srf
as defined in the Steven Maguire provider.
The header contains the content-type application/x-www-form-urlencoded (I've seen a lot of post where this was what caused the error).
Some of my code :
$this->provider = new Microsoft([
'clientId' => MicrosoftGraphConstants::CLIENT_ID,
'clientSecret' => MicrosoftGraphConstants::CLIENT_SECRET,
'redirectUri' => MicrosoftGraphConstants::REDIRECT_URI,
'urlAuthorize' => MicrosoftGraphConstants::AUTHORITY_URL . MicrosoftGraphConstants::AUTHORIZE_ENDPOINT,
'urlAccessToken' => MicrosoftGraphConstants::AUTHORITY_URL . MicrosoftGraphConstants::TOKEN_ENDPOINT,
'urlResourceOwnerDetails' => MicrosoftGraphConstants::RESOURCE_ID,
'scope' => MicrosoftGraphConstants::SCOPES
]);
if ($_SERVER['REQUEST_METHOD'] === 'GET' && !isset($_GET['code']))
{
// Try getting access token from Database
$workingAccount = $GLOBALS['AppUI']->getState('working_account');
if (isset($workingAccount))
{
// DB access
$DB = new DatabaseConnection();
$dbAccess = $DB->getConnection();
$contactData = DBUserUtils::getContactDataFromEmail($GLOBALS['AppUI']->getState('working_account'), $dbAccess);
// If at least one user contact found
if (!is_null($contactData))
{
// If has refresh token => fill session variables using refresh token
if (!is_null($contactData['contact_refreshToken']))
{
log_msg('debug.log', 'Has refresh token');
$GLOBALS['AppUI']->setState('preferred_username', $contactData['contact_email']);
$GLOBALS['AppUI']->setState('given_name', $contactData['contact_first_name']." ".$contactData['contact_last_name']);
// Get new tokens
$newAccessToken = $this->provider->getAccessToken('refresh_token', [
'refresh_token' => $contactData['contact_refreshToken']
]);
// Update tokens and DB
$GLOBALS['AppUI']->setState('refresh_token', $newAccessToken->getRefreshToken());
$GLOBALS['AppUI']->setState('access_token', $newAccessToken->getToken());
DBOAuthUtils::updateTokenForUser($contactData['contact_id'], $GLOBALS['AppUI']->getState('refresh_token'), $dbAccess);
$this->redirectTo($redirectURL);
}
else
{
$this->getAccessToken();
}
}
else
{
$this->getAccessToken();
}
}
else
{
$this->getAccessToken();
}
function getAccessToken(){
$accessToken = $this->provider->getAccessToken('password', [
'username' => '*************',
'password' => '********',
'scope' => MicrosoftGraphConstants::SCOPES
]);
}
During the first try it doesn't pass the if (isset($workingAccount)) condition (as expected) and go straight to the last else.
Code is a bit ugly for now but I don't think it has an impact on my problem.
Any help would be appreciated !
Thanks
Edit : added code
That helped me, the problem was that I need to use Azure Active Directory and not Azure AD 2.0.
Problem solved !
I have installed laravel 5.3 and passport pakage.
I followed the documentaition step by step
I can use the following route POST /oauth/token with the following parameters
username
password
client_secret
grant_type
client_id
and I get the following response
{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "access token here",
"refresh_token": "refresh token here"
}
then I request GET /api/user
with the following header
Authorization = "Bearer access token here"
accept = application/json (optional)
and this is work fine and so all apis.
the problem I have is the user who I authinticated and entered his username and password in the first request and return me back the access token is a user I have created from laravel web view /register
How can I create new user or register new user from the api route file
like POST /api/register
the user at first time need to register to be authinticated after that.
Should I create this route without oauth to register then if success the registration he request POST /oauth/token to be authinticated or what?
Am I missing something ??
update
the clent_secret is it right to be constant in all users requests or each user should have diffrent clent_secret, and if it is how to create aclent secret if it neaded to authinticate user ?
The fastest way to do this is adding an exception to your verifyCsrfToken.php class
protected $except = [
'register'
];
Then you can post to your register model, and afterwards accessing this account with oauth/token.
If i understand your question correctly, you want to register new user and get token after registration from /oauth/token. For this you can use a proxy. I have used something similar and i followed the following steps. This works for both Login and Register
Register the user and send a HTTP request to /oauth/token endpoint from your register method
public function register(RegisterRequest $request)
{
$user = User::create($request->all());
$response = $this->authenticationProxy->attemptLogin($request->email, $request->password);
return response()->json(compact('response', 'user'), 201);
}
Then in your proxy class, call the /oauth/token
public function attemptLogin($email, $password)
{
$http = new GuzzleHttp\Client;
$response = $http->post('http://your-app.com/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => env('CLIENT_ID'),
'client_secret' => env('CLIENT_SECRET'),
'username' => $email,
'password' => $password,
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}
Hope this helps. You can use similar approach for login as well.