我已将oauth2服务器与Laravel集成。但是我有点困惑的是使用通过oauth2保护的资源的webapp我们只通过授权服务器登录,就像有“登录Google”的网站一样,我们实际上没有登录表单在我们的网站上。所以我想知道如何在用户返回时识别用户?
我的意思是我们通过仅在webapp上下文中相关的webapp提供个性化,因此我们在那里有一个数据库,只需通过user_id将个性化链接到用户,我们还存储user_id => access_token对以及后续请求中我们使用该访问令牌。
当用户首次要求他们授予访问权限时,这一切都很有效。但是在后续请求中,授权服务器再次要求用户授予对webapp的访问权限,而不仅仅是登录。 / p>
我在这里做错了什么或应该是授权服务器 - 在识别预先存在的client_id和user_id时自动授权客户端?并且webapp应该在每个后续会话中获得新的access_token(其中user_id已从用户会话/ cookie中删除,因此我们必须要求授权服务器再次告诉我们该用户是谁)。
<?php
use Illuminate\Support\MessageBag;
use \League\OAuth2\Server;
use League\OAuth2\Server\Util\RedirectUri;
use Toddish\Verify\UserDeletedException;
use Toddish\Verify\UserDisabledException;
use Toddish\Verify\UserNotFoundException;
use Toddish\Verify\UserPasswordIncorrectException;
use Toddish\Verify\UserUnverifiedException;
class oAuthController extends BaseController {
public function __construct() {
// Initiate the request handler which deals with $_GET, $_POST, etc
$request = new Server\Util\Request();
// Initiate a new database connection
$connectionString = '';
$connectionString .= DB::Connection()->getConfig('driver') . '://';
$connectionString .= DB::Connection()->getConfig('username') . ':';
$connectionString .= DB::Connection()->getConfig('password') . '@';
$connectionString .= DB::Connection()->getConfig('host') . '/';
$connectionString .= DB::Connection()->getConfig('database');
$db = new Server\Storage\PDO\Db( $connectionString );
// Create the auth server, the three parameters passed are references
// to the storage models
$this->authserver = new Server\Authorization(
new Server\Storage\PDO\Client,
new Server\Storage\PDO\Session,
new Server\Storage\PDO\Scope
);
// Enable the authorisation code grant type
$this->authserver->addGrantType(new Server\Grant\AuthCode( $this->authserver ));
$this->authserver->setScopeDelimeter(',');
}
public function getIndex() {
try {
// Tell the auth server to check the required parameters are in the
// query string
$grant = $this->authserver->getGrantType('authorization_code');
$params = $grant->checkAuthoriseParams();
// Save the verified parameters to the user's session
Session::put('client_id', $params['client_id']);
Session::put('client_details', $params['client_details']);
Session::put('redirect_uri', $params['redirect_uri']);
Session::put('response_type', $params['response_type']);
Session::put('scopes', $params['scopes']);
// Redirect the user to the sign-in route
return Redirect::action('OauthController@getSignin');
} catch(Server\Exception\ClientException $e) {
/**
* Handle all the fatal errors we shouldn't send back to the client.
*/
if(Server\Authorization::getExceptionType($e->getCode()) == 'invalid_client') {
return View::make('oauth.client-error')
->with(Lang::get('oauth.errors.fatal.invalid'))
->with('apiMessage', $e->getMessage());
} elseif(Str::contains($e->getMessage(), 'Check the "redirect_uri" parameter')) {
return View::make('oauth.client-error')
->with(Lang::get('oauth.errors.fatal.redirectUri'))
->with('apiMessage', $e->getMessage());
} elseif(Str::contains($e->getMessage(), 'Check the "client_id" parameter')) {
return View::make('oauth.client-error')
->with(Lang::get('oauth.errors.fatal.clientId'))
->with('apiMessage', $e->getMessage());
} else {
/**
* if we got here we know that the client_id and redirect_uri are filled but we cannot assume they are
* valid we need to validate the credentials to decide whether to send the user back to the redirect_uri * with the error or handle it in house
*/
$client = $this->authserver->getStorage('client');
$clientDetails = $client->getClient(Input::get('client_id'),
null,
urldecode(Input::get('redirect_uri')),
$grant->getIdentifier());
/**
* Invalid client details, let's handle this issue first.
*/
if($clientDetails === false) {
return View::make('oauth.client-error')
->with(Lang::get('oauth.errors.fatal.invalid'))
->with('apiMessage', $this->authserver->getExceptionMessage('invalid_client'));
}
/**
* Valid client credentials - let's redirect the resource owner back to the client with the error.
*/
$redirectResponse = [
'error' => Server\Authorization::getExceptionType($e->getCode()),
'error_description' => $e->getMessage()
];
return Redirect::to(RedirectUri::make(Input::get('redirect_uri'), $redirectResponse));
}
} catch(Exception $e) {
/**
* This is a general exception so we should pass this back off to the client with the server_error error
*/
$redirectResponse = [ ];
}
}
public function getSignin() {
$params = $this->getParams(false);
// User is signed in
if($params['user_id'] !== null) {
return Redirect::action('OauthController@getAuthorise');
} else {
return View::make('oauth.signin', $params);
}
}
public function postSignin() {
try {
$validator = Validator::make(
Input::only([ 'identifier', 'password' ]),
[ 'identifier' => [ 'required' ], 'password' => [ 'required' ] ]
);
if($validator->fails()) {
$errors = $validator->getMessageBag();
} else {
Auth::attempt(Input::only([ 'identifier', 'password' ]), Input::get('remember'));
Session::put('user_id', Auth::user()->id);
return Redirect::action('OauthController@getAuthorise');
}
} catch(UserNotFoundException $e) {
$errors = new MessageBag( [ 'identifier' => Lang::get('oauth.errors.signIn.userNotFound') ] );
} catch(UserUnverifiedException $e) {
$errors = new MessageBag( [ 'identifier' => Lang::get('oauth.errors.signIn.userNotVerified') ] );
} catch(UserDisabledException $e) {
$errors = new MessageBag( [ 'identifier' => Lang::get('oauth.errors.signIn.userDisabled') ] );
} catch(UserDeletedException $e) {
$errors = new MessageBag( [ 'identifier' => Lang::get('oauth.errors.signIn.userDeleted') ] );
} catch(UserPasswordIncorrectException $e) {
$errors = new MessageBag( [ 'password' => Lang::get('oauth.errors.signIn.userWrongPassword') ] );
} catch(Exception $e) {
$errors = new MessageBag( [ 'generic' => $e->getMessage() ] );
}
return Redirect::action('OauthController@getSignin')
->withErrors($errors)
->withInput(Input::only([ 'identifier', 'remember' ]));
}
private function getParams($doUserIdCheck = true) {
// Retrieve the auth params from the user's session
$params['client_id'] = Session::get('client_id');
$params['client_details'] = Session::get('client_details');
$params['redirect_uri'] = Session::get('redirect_uri');
$params['response_type'] = Session::get('response_type');
$params['scopes'] = Session::get('scopes');
// Check that the auth params are all present
foreach($params as $key => $value) {
if($value === null) {
// Throw an error because an auth param is missing - don't
// continue any further
$errors = new MessageBag( [ 'error' => 'The request is missing the ' . $key . ' key' ] );
die();
}
}
// Get the user ID
$params['user_id'] = Session::get('user_id');
// User is not signed in so redirect them to the sign-in route (/oauth/signin)
if($doUserIdCheck && $params['user_id'] === null) {
return Redirect::action('OauthController@getSignin');
}
return $params;
}
public function getAuthorise() {
$params = $this->getParams();
//if it's not an array we have got back a redirect request
if(! is_array($params)) {
return $params;
}
// Check if the client should be automatically approved
$autoApprove = ( $params['client_details']['auto_approve'] === '1' ) ? true : false;
// Process the authorise request if the user's has clicked 'approve' or the client
if($autoApprove) {
// Generate an authorisation code
$code = $this->authserver->getGrantType('authorization_code')
->newAuthoriseRequest('user', $params['user_id'], $params);
// Redirect the user back to the client with an authorisation code
return Redirect::to(
RedirectUri::make(
$params['redirect_uri'],
[ 'code' => $code, 'state' => isset( $params['state'] ) ? $params['state'] : '' ]));
}
// The client shouldn't automatically be approved so show them a form
return View::make('oauth.authorise', $params);
}
public function postAuthorise() {
$params = $this->getParams();
//if it's not an array we have got back a redirect request
if(! is_array($params)) {
return $params;
}
if(Input::get('approve') !== null) {
if(Input::get('terms') === null) {
$e = new MessageBag( [ 'terms' => Lang::get('oauth.errors.authorize.termsNotAccepted') ] );
return Redirect::action('OauthController@getAuthorise')->withErrors($e);
}
// Generate an authorisation code
$code = $this->authserver->getGrantType('authorization_code')
->newAuthoriseRequest('user', $params['user_id'], $params);
// Redirect the user back to the client with an authorisation code
$redirectResponse = [ 'code' => $code, 'state' => isset( $params['state'] ) ? $params['state'] : '' ];
}
// If the user has denied the client so redirect them back without an authorisation code
if(Input::get('deny') !== null) {
$redirectResponse = [ 'error' => 'access_denied',
'error_message' => $this->authserver->getExceptionMessage('access_denied'),
'state' => isset( $params['state'] ) ? $params['state'] : '' ];
}
if(isset( $redirectResponse )) {
return Redirect::to(RedirectUri::make($params['redirect_uri'], $redirectResponse));
} else {
//we didn't get a valid response from the user, let's start again
return Redirect::action('OauthController@getIndex');
}
}
public function postAccessToken() {
try {
// Tell the auth server to issue an access token
$this->authserver->setAccessTokenTTL(15768000); //ask user for permissions every half year
$response = $this->authserver->issueAccessToken();
return Response::json($response, 200, [ 'cache-control' => 'Cache-Control', 'Pragma' => 'no-cache' ]);
} /*
|--------------------------------------------------------------------------
| An error occurred inside the library
|--------------------------------------------------------------------------
*/
catch(Server\Exception\ClientException $e) {
// Throw an exception because there was a problem with the client's request
$exceptionType = Server\Authorization::getExceptionType($e->getCode());
$response = [
'error' => $exceptionType,
'error_description' => $e->getMessage()
];
// Grab the code out of the header string
$code = substr(current(Server\Authorization::getExceptionHttpHeaders($exceptionType)), 9, 3);
return Response::json($response, $code);
} /*
|--------------------------------------------------------------------------
| An error occurred outside the library, probably a generic server error
|--------------------------------------------------------------------------
*/
catch(Exception $e) {
// Throw an error when a non-library specific exception has been thrown
$response = [ 'error' => 'undefined_error', 'error_description' => $e->getMessage() ];
return Response::json($response, 500);
}
}
}
答案 0 :(得分:0)
这是因为OAuth通常是授权协议:
使用授权服务器进行身份验证的用户已授予 Laravel webapp允许调用端点的权限 受授权服务器保护。它会使用
access_token
这样做。
您想要的是将其用作在您的系统中将用户标识为有效用户的方法。您可以通过调用AS上的userinfo
端点(使用access_token
)然后在服务器中为该用户创建会话来执行此操作。看来Laravel的方式为manually logging in users,所以你会在userinfo
成功返回后调用该方法。 (经过身份验证的用户的代理)。
userinfo
是一个端点,通常返回有关用户的信息(例如电子邮件,姓名,ID等)。您可以使用该信息并将其与您身边的用户记录相关联。