Laravel 7 cognito used in web and apps - laravel

I want to build laravel 7 with aws cognito and use this package aws-sdk-php-laravel.
This project will be made for the web & apps.
so how the laravel handle login from apps then apps get API from web with same token from cognito?
This is my first time use cognito, usually use auth-jwt.

After many tries without package
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CognitoController extends Controller
{
private $key;
private $secret;
private $region;
private $version;
private $client_id;
private $client_secret;
private $user_pool_id;
private $aws;
private $client;
public function __construct()
{
$this->key = 'xxxxxx';
$this->secret = 'xxxxxx';
$this->region = 'xxxxxx';
$this->version = 'latest';
$this->client_id = 'xxxxxx';
$this->client_secret = 'xxxxxx';
$this->user_pool_id = 'xxxxxx';
$config = [
'credentials' => [
'key' => $this->key,
'secret' => $this->secret,
],
'region' => $this->region,
'version' => $this->version,
'app_client_id' => $this->client_id,
'app_client_secret' => $this->client_secret,
'user_pool_id' => $this->user_pool_id,
];
$this->aws = new \Aws\Sdk($config);
$this->client = $this->aws->createCognitoIdentityProvider();
}
public function login()
{
$username = 'guest';
$password = 'password';
$result = $this->client->adminInitiateAuth([
'AuthFlow' => 'ADMIN_NO_SRP_AUTH',
'AuthParameters' => [
'USERNAME' => $username,
'PASSWORD' => $password,
'SECRET_HASH' => $this->secretHash($username),
],
'ClientId' => $this->client_id,
'UserPoolId' => $this->user_pool_id,
]);
$access_token = $result->get('AuthenticationResult')['AccessToken'];
echo '<pre>';
print_r( $result );
echo '<br/>';
print_r( $access_token );
echo '</pre>';
}
public function register()
{
$username = 'guest';
$password = 'password';
$email = 'guest#email.com';
$phone_number = '+819000000000';
$result = $this->client->signUp([
'ClientId' => $this->client_id,
'Password' => $password,
'SecretHash' => $this->secretHash($username),
'UserAttributes' => [
[
'Name' => 'phone_number',
'Value' => $phone_number,
],
[
'Name' => 'email',
'Value' => $email,
]
],
'Username' => $username
]);
echo '<pre>';
print_r( $result );
echo '</pre>';
}
public function register_confirm()
{
$username = 'guest';
$confirmationCode = '123456'; // from email verification code
$result = $this->client->confirmSignUp([
'ClientId' => $this->client_id,
'Username' => $username,
'SecretHash' => $this->secretHash($username),
'ConfirmationCode' => $confirmationCode,
]);
echo '<pre>';
print_r( $result );
echo '</pre>';
}
public function list()
{
$search = ['UserPoolId' => $this->user_pool_id];
$users = $this->client->listUsers($search)->toArray();
echo '<pre>';
print_r( $users );
echo '</pre>';
}
private function secretHash($username) {
$clientId = $this->client_id;
$clientSecret = $this->client_secret;
$s = hash_hmac('sha256', $username . $clientId, $clientSecret, true);
return base64_encode($s);
}
}
token from auth cognito is it the same as the token when use JWTAuth?
Laravel Socialite doesn't have a cognito platform yet

You can configure AWS Cognito for OAuth and use one of the Laravel Oauth plugin to connect and authenticate with Cognito. I hope you will be storing user credentials in AWS Cognito User Pool.
Complete documentation (High Level) of AWS Cognito - https://www.slideshare.net/awsugkochi/acdkochi19-enterprise-grade-security-for-web-and-mobile-applications-on-aws
Documentation of AWS Cognito architecture for OAuth configuration - https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/
Documentation of Laravel Socialite to connect with AWS Cognito over OAuth and get authentication.

Related

Laravel: Auth Midleware returns 401 (Unauthorized)

I have an issue with authenticating a user. This is the Authentication method in my controller:
public function authenticate(Request $request){
$user = User::where('username', $request->username)->first();
$user_model = new User;
$return_credentials = [
'message' => "User does not exist.",
'status' => false,
'user_details' => ""
];
if(!empty($user) && !is_null($user)){
$remember = Str::random(60);
if(\Auth::attempt(['username' => $request->username, 'password' => $request->password, 'verified' => '1'], $remember)){
$user = \Auth::user();
$token_result = $user->createToken('Personal Access Token');
$token = $token_result->token;
$token->expires_at = Carbon::now()->addWeeks(1);
$return_credentials['message'] = "User Successfully Logged in.";
$return_credentials['status'] = true;
$token->save();
}else{
$return_credentials['message'] = "User Failed to Log in.";
$return_credentials['status'] = false;
}
}
$return_credentials['user_details'] = $user;
return response()->json($return_credentials);
}
Every time I access a route using(this middleware):
Route::group(['middleware' => 'auth:api'], function() {
Route::get('user', '\App\Http\Controllers\UserController#verifyUserLoggedIn');
});
It returns:
GET http://..../api/auth/user 401 (Unauthorized)
Q: Am I missing a step or anything?
Add auth:api in your app\Http\kernel.php :
'api' => [
'throttle:60,1',
'bindings',
'auth:api',
],

Laravel passport create token doesnt work on plesk server

I use passport in my laravel project to authenticate users by api. API work correctly on my local host. But after i deploy it on Plesk server token doesnt create. Always show Server Error.
public function login(Request $request) {
$validator = Validator::make($request->all(),[
'email' => 'required',
'password' => 'required',
]);
if($validator->fails()) {
return response()->json(["validation errors" => $validator->errors()]);
}
$email = $request->email;
$password = $request->password;
error_log($password);
$user = DB::table("users")->where([["email", "=", $email]])->first();
if(is_null($user)) {
return response()->json(["success" => false, "message" => "User doesn't exist"]);
}
if(Auth::attempt(['email' => request('email'), 'password' => request('password')])) {
$user = Auth::user();
$token = $user->createToken('token')->accessToken;
$success['success'] = true;
$success['user'] = $user;
$success['message'] = "Success! you are logged in successfully";
$success['token'] = $token;
return response()->json(['success' => $success ], 200);
} else {
return response()->json(['error' => 'Unauthorised'], 401);
}
}
$token = $user->createToken('token')->accessToken;
This line throw error
Problem was in my AuthServiceProvider
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'Medicare\Model' => 'Medicare\Policies\ModelPolicy',
];
public function boot()
{
$this->registerPolicies();
Passport::routes();
//
}
}
After i commented 'Medicare\Model' => 'Medicare\Policies\ModelPolicy' everything works fine.

Laravel - Call to undefined method App\\User::getAvatarUrlAttribute()

I am using Laravel-5.8 as backend for an application. I have written all the Api for the endpoints.
Laravel: ApiController
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use App\User;
use App\Activity;
use Avatar;
use Storage;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Mail;
use Audit;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
class ApiController extends Controller
{
public $successStatus = 200;
public function __construct() {
}
protected function guard()
{
return Auth::guard();
}
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth()->factory()->getTTL() * 60,
'user' => auth()->user()->email
], 200);
}
public function returnResponse($success, $data, $errorCode = 0, $message = false) {
$response = array();
$response['success'] = $success;
$response['message'] = isset($message) ? $message : '';
if ($errorCode) {
$response['errorCode'] = isset($errorCode) ? $errorCode : 0;
}
$response['data'] = $data;
return response()->json($response, 200);
}
public function register(Request $request) {
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|string|email|max:255|unique:users',
// 'phone' => 'required',
// 'password' => 'required',
'password' => 'required|string|min:6',
// 'password' => 'required|string|min:6|confirmed',
'password_confirmation' => 'required|same:password',
]);
if ($validator->fails()) {
return $this->returnResponse(false, ['error' => $validator->errors()], 1, 'Invalid User Data');
}
$input = $request->all();
// code for check email / username / phone exist or not
if(isset($input['email'])){
$alreadyExist = User::where(function ($query) use ($input) {
$query->where('email', '=', $input['email']);
})->get();
}
if (count($alreadyExist->toArray()) > 0) {
return $this->returnResponse(false, ['error' => 'Email Already Exist'], 1, 'User Data Already Exist');
}
// code for register user
$user = new User();
$user->name = $input['name'];
$user->email = $input['email'];
$user->password = bcrypt($input['password']);
$user->save();
$mainData = array();
$mainData['to'] = $user->toArray()[0]['email'];
$mainData['from'] = "support#tsllimited.com";
$mainData['subject'] = "Successful Signup";
$mainData['content'] = "Your signup was successful, you can login with the credentials.";
$this->mailSend($mainData);
Activity::create([
'user_id' => $user->id,
'owner_id' => $user->client_id,
'type' => "User Registration",
'title' => "Successful Signup of User",
'state' => 2,
'created_at'=> date('Y-m-d H:i:s')
]);
$success = array();
$success['user_id'] = $user->id;
$success['user']=$user;
return $this->returnResponse(true, $success, 0, 'User registered successfully');
}
public function login(Request $request) {
$authenticated = false;
$validator = Validator::make($request->all(), [
'email' => 'required|string|email',
'password' => 'required|string',
'remember' => 'boolean'
]);
if ($validator->fails()) {
return $this->returnResponse(false, ['error' => $validator->errors()], 1, 'Invalid User Data');
}
$remember = request('remember') ? true : false;
if (Auth::guard('web')->attempt(['email' => request('email'), 'password' => request('password')], $remember)) {
$authenticated = true;
}
if ($authenticated == true) {
$user = Auth::guard('web')->user();
$date = date('Y-m-d');
$success['userId'] = $user->id;
$success['avatar'] = url('/storage/user') . '/' . $user->avatar;
$success['email'] = $user->email;
$success['token'] = $user->createToken('MyApp')->accessToken;
return $this->returnResponse(true, $success);
} else {
$success = array();
return $this->returnResponse(false, $success, 1, 'Invalid User Credential');
}
}
}
api.php
Route::group([
], function () {
Route::post('login', 'ApiController#login');
Route::post('register', 'ApiController#register');
Route::post('forgetPassword', 'ApiController#forgetPassword');
Route::group([
'middleware' => 'auth:api'
], function() {
Route::get('logout', 'AuthController#logout');
Route::get('user', 'AuthController#user');
});
});
I stalled and configured Laravel Passport and also Spatie. I have checked the code and don't know what the error really is. When I test the resgister Post Request on the POSTMAN, I got the error shown below:
See the POSTMAN preview side:
What could have caused the error and how do I resolve it?
You do not have the column avatar on your users table.
Maybe you did not use the trait you need in your User class
class User extends Authenticatable {
use HasAvatar;
// ...
}
I eventually solved the problem myself. The issue is that, I forgot to add:
public function getAvatarUrlAttribute()
{
return Storage::url('avatars/'.$this->id.'/'.$this->avatar);
}
to User Model.
Thanks

How to generate access_token without username and password

I am trying to make an API with Passport. If a user tries to login or signs up with Socialite, find user than generate access_token then redirect to the frontend with access_token in URL parameters.
I tried to register and login than generate access_token with user email and the default password, which is not suitable for security.
try {
$serviceUser = Socialite::driver($service)->stateless()->user();
} catch (\Exception $e) {
return redirect(config('app.client_url').'/auth/social-callback?error=Unable to login using '.$service.'. Please try again'.'&origin=login');
}
$email = $serviceUser->getEmail();
$name = $serviceUser->getName();
$user = $this->getExistingUser($serviceUser, $email, $service);
$newUser = false;
if (!$user) {
$newUser = true;
$user = new User;
$user->name = $name;
$user->email = $email;
$user->username = Str::random(10);
if ($service === 'facebook') {
$user->image = $serviceUser->avatar;
}
$user->verify = true;
$user->save();
}
if ($this->needsToCreateSocial($user, $service)) {
Social::create([
'user_id' => $user->id,
'social_id' => $serviceUser->getId(),
'service' => $service
]);
}
$http = new Client;
$response = $http->post(config('app.url').'/oauth/token', [
'form_params' => [
'grant_type' => 'password',
'client_id' => '2',
'client_secret' => 'oBKWxgF2fDvrxwA05ciapwy4JYKaHxzhGzr6D24X',
'username' => $email,
'password' => 'gebdandi',
'scope' => '',
],
]);
$body = json_decode((string) $response->getBody(), true);
$accessToken = $body['access_token'];
return redirect(config('app.client_url').'/social-callback?token='.$accessToken.'&origin='.($newUser ? 'register' : 'login'));
I can't find any solution in the documentation.
after reading all documentation i found solution in this documentation
i did like this
edit authserviceprovider like this
public function boot()
{
$this->registerPolicies();
Passport::routes();
Passport::personalAccessClientId(1);
Passport::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30));
}
added code in controller like this
$accessToken = $user->createToken('access_token')->accessToken;
thanks for laravel Team for provide good documentation

Laravel socialite with passport unsupported grant type

I am trying to generate a bearer token with access and refresh tokens after user authenticates with socialite.
public function handleProviderCallback($provider, EmailConfirmationMailer $mailer)
{
$user = Socialite::driver($provider)->user();
if(User::where('email', '=', $user->getEmail())->exists()){
$exist_user = User::where('email', '=', $user->getEmail())->first();
Auth::loginUsingId($exist_user->id);
$http = new GuzzleHttp\Client;
$response = $http->post('http://localhost:8000/oauth/token', [
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => 'the-refresh-token',
'client_id' => 1,
'client_secret' => 'c4ojSmOjl04QrshdSXlOmbKUOIxm6zqyhND34AT0',
'scope' => '',
],
]);
return json_decode((string) $response->getBody(), true);
}else{
//create new user here
}
}
I got the error from vendor\laravel\socialite\src\Two\AbstractProvider.php
user function, message is "".
public function user()
{
if ($this->hasInvalidState()) {
throw new InvalidStateException;//here is the highlighted
}
$response = $this->getAccessTokenResponse($this->getCode());
$user = $this->mapUserToObject($this->getUserByToken(
$token = Arr::get($response, 'access_token')
));
return $user->setToken($token)
->setRefreshToken(Arr::get($response, 'refresh_token'))
->setExpiresIn(Arr::get($response, 'expires_in'));
}
What is the best practice for this situation? Any help is greatly appreciated.
resorted to generate accessToken with no refreshToken:
public function handleProviderCallback($provider)
{
$user = Socialite::driver($provider)->user();
if(User::where('email', '=', $user->getEmail())->exists()){
$existUser = User::where('email', '=', $user->getEmail())->first();
Auth::login($existUser,true);
//remove existing tokens from user
$tokenResult = $existUser->createToken('Personal Access Token');
return \response()->json([
'token_type' => 'Bearer',
'expires_in' => $tokenResult->token->expires_at->diffInSeconds(Carbon::now()),
'access_token' => $tokenResult->accessToken,
'info' => 'Existing user'
]);
}else{
//create new user entry
}
}

Resources