-
Notifications
You must be signed in to change notification settings - Fork 20
RFC: Separate authorization and token endpoints #42
RFC: Separate authorization and token endpoints #42
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I annotated my intentions in the changeset
src/AuthFlowFactoryTrait.php
Outdated
* Provides helper methods for authorization flow related factories | ||
* @internal | ||
*/ | ||
trait AuthFlowFactoryTrait |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though this is discouraged by some, traits offer a solution to re-use code without building an inheritance hell. Plus, there is no official decision that forbids them.
This code is used in 3 factories and I don't see any benefit in duplicating this code three times which needs maintanence in three files if something needs to be changed in this code segment.
I don't know why git magically thinks this was moved from the OAuth2MittlewareFactory
, it was not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need this Trait. A simple $container->get(AuthorizationServer::class)
is enough in each factory class. All the checks present in AuthFlowFactoryTrait
are performed by the service manager by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree. Getting rid of the additional checks will simplify the codebase and increase maintainability.
I just ported it from the existing OAuth2MiddlewareFactory
, because I didn't know if there was a specific intend for the specialized exception.
// authenticated user and the approval | ||
$authRequest->setAuthorizationApproved(false); | ||
|
||
return $handler->handle($request->withAttribute(AuthorizationRequest::class, $authRequest)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pass the the auth request via the server request object to the next handler to complete it.
(ensure authentication, giving consent, etc ...). This gives consumers the freedom to act according to their business needs
use Psr\Http\Message\ResponseInterface; | ||
use function sprintf; | ||
|
||
class AuthorizationMiddlewareFactory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed the name fom OAuth2MiddlewareFactory
according to the middleware and deduplicated code.
src/TokenEndpointHandler.php
Outdated
|
||
if (strtoupper($request->getMethod()) !== 'POST') { | ||
return $response->withStatus(501); // Method not implemented | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As for the Authorization endpoint, do we need this here, or should this be delegated to the
route()
call? Anyways it should be consistent in both cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove this, since you have splitted the authorization endpoint from the token endpoint.
@tux-rampage thanks for this PR, it's a great improvement from an architectural point of view. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please review my feedbacks, thanks!
@ezimuel Thanks for the feedback. I'll review and update the PR accordingly the next days. |
Thanks for tackling this issue. This was something I was also attempting to look at myself. I'm glad you beat me to it. ;) One thing that I was having an issue with was the serialization and storage of the outh2 auth request object. Perhaps I didn't see it, but how are you saving the request to be approved on approval requests, or how were you seeing this being addressed going forward? |
@wshafer, I had an interesting chat with @xtreamwayz in slack about the issue. I'd not recommend to serialize the OAuth2 Request Object. That would require you to have knowledge of iternals of Leaque's OAuth2 library. To me that looks like a not so good idea. One option would be to keep the HTTP-Request parameters and Redirect to the authorization endpoint with these parameters when ready. In the OpenID provider that I am currently implementing, I use Angular as Frontend, so it's a one-pager and I can just render the UI view (parameterized) when user interaction is required. Additionally I have a middleware converting HTTP 301/302 redirects to JSON 200 responses and the redirect info in the response body so Angular will handle it. |
I'll add some examples to the docs and drop a comment when this PR is ready for another review (there are still some tests missing). |
@ezimuel I've completed the PR, added docs and the CHANGELOG entries (feel free to rephrase - I'll apreciate any improvements). Sorry that this took a bit longer and thanks for your patience. The drop of coverage is caused by the |
@tux-rampage thanks for this great work! I'll review it asap. |
@ezimuel Had an ytime to review this, yet? Let me know if I can support you. |
@tux-rampage thanks for the hard work! |
According to the OAuth2 RFC 6749 the authorization and token endpoint provide two different concerns and should be separated.
Details
As of section 3.1, the authorization endpoint is designed
to Initiate an interactive authorization flow, where the user (resource owner) may be asked to authenticate against the authorization server as well as for consent to provide access to the requesting party. This endpoint will either redirect to the requesting party with an access code, the access token, or an error or should display an error page to the resource owner when the requesting party is invalid as defined in section 3.1.2.4. This endpoint must allow GET requests and may allow POST.
In contrast section 3.2, the token endpoint is designed for
automated
access token provision without user interaction. Usually this endpoint is used on the server side of the application to prevent access token exposure to the user agent.With the current single middleware implementation consumers will face a bunch of issues:
UserEntityInterface
implementation or to set the approval flag.Therefore this PR suggests to separate this MiddleWare (Which actually is a Request Handler) into 3 parts (Consider these classes are in namespace
Zend\Expressive\Authentication\OAuth2
):TokenHandler
- Provides the implementation of the OAuth2 Token endpoint.AuthorizatonMiddleware
- Prepares and validates the OAuth2 authrization request and passes it with the request object to the next handler(s)AuthorizationHandler
Uses theLeague\OAuth2\Server\RequestTypes\AuthorizationRequest
from the request and completes the response (proper redirecting to the requesting party)It is up to the consumer to provide the User entity and approval information to the authorization request instance via a middleware. This gives consumers the flexibility to handle this step in any way they need to fulfill their business needs.
Example:
Are you creating a new feature?
develop
(:warning: missing) branch, and submit against that branch.CHANGELOG.md
entry for the new feature.Is this related to quality assurance?