Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help needed] Adding authorization level to access-token #1103

Closed
Richard87 opened this issue Apr 6, 2020 · 4 comments
Closed

[Help needed] Adding authorization level to access-token #1103

Richard87 opened this issue Apr 6, 2020 · 4 comments

Comments

@Richard87
Copy link

Hi!

I can add the required authentication security level to my AuthCode, since I know it at the time, but how can I transfer that knowledge to the AccessToken (either in the database, or as a claim in the JWT)

I'm already using OpenID Connect, but I'm not sure how to transfer that "knowledge" properly...
I need to know if the user is authenticated with Email/Password, 2-FA with a SMS-code, or 2FA from an external auth provider (external OIDC service)

Relevant other issues I found:
#885
#442
#672

@Richard87
Copy link
Author

Richard87 commented Apr 6, 2020

I don't need to save it in the JWT, but I need to at least save it to the accompanying AccessToken in the database...

@Richard87 Richard87 reopened this Apr 6, 2020
@Richard87
Copy link
Author

Richard87 commented Apr 7, 2020

My hacky solution...

  1. Add a function "getAuthCode" in AuthCodeRepositoryInterface, so we can fetch it later
  2. Modify the access token
  • Fetch the request token first, so we can access the encyrpted AuthCode
  1. Modify AccessToken, to include our new claims in __toString()

First get a hold of the request object

class AuthCodeGrantWithProvider extends AuthCodeGrant
{

    private ?ServerRequestInterface $request = null;

    public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, DateInterval $accessTokenTTL)
    {
        $this->request = $request;
        return parent::respondToAccessTokenRequest($request, $responseType, $accessTokenTTL); // TODO: Change the autogenerated stub
    }

    protected function issueAccessToken(DateInterval $accessTokenTTL, ClientEntityInterface $client, $userIdentifier, array $scopes = [])
    {
        /** @var TokenRepository $authCodeRepo */
        $authCodeRepo = $this->accessTokenRepository;

        $encryptedAuthCode = $this->getRequestParameter('code', $this->request, null);
        $authCodePayload = json_decode($this->decrypt($encryptedAuthCode), false, 512, JSON_THROW_ON_ERROR);

        /** @var AuthCode $authCode */
        $authCode = $authCodeRepo->getAuthCode($authCodePayload->auth_code_id);

        /** @var AccessToken $accessToken */
        $accessToken = parent::issueAccessToken($accessTokenTTL, $client, $userIdentifier, $scopes);
        $accessToken->setAuthProvider($authCode->getAuthProvider());
        $accessToken->setSecurityLevel($authCode->getSecurityLevel());

        return $accessToken;
    }

}

AccessToken

    /**
     * Generate a JWT from the access token
     *
     * @param CryptKey $privateKey
     *
     * @return Token
     */
    private function convertToJWT(CryptKey $privateKey)
    {
        return (new Builder())
            ->permittedFor($this->getClient()->getIdentifier())
            ->identifiedBy($this->getIdentifier())
            ->issuedAt(time())
            ->canOnlyBeUsedAfter(time())
            ->expiresAt($this->getExpiryDateTime()->getTimestamp())
            ->relatedTo((string) $this->getUserIdentifier())
            ->withClaim(self::CLAIM_SCOPES, $this->getScopes())
            ->withClaim(self::CLAIM_PROVIDER, $this->getAuthProvider())
            ->withClaim(self::CLAIM_SECURITY_LEVEL, $this->getSecurityLevel())

            ->getToken(
                new Sha256(),
                new Key($privateKey->getKeyPath(),
                    $privateKey->getPassPhrase())
            );
    }

    /**
     * Generate a string representation from the access token
     */
    public function __toString()
    {
        return (string) $this->convertToJWT($this->privateKey);
    }

@Sephster
Copy link
Member

Sephster commented Apr 7, 2020

Hi @Richard87 - it would probably be best to have this stored on the JWT as a custom claim although changing the finalizeScopes method might also work for you.

At the moment, I'm trying to push through a large PR on the device code grant so don't have time to look at this just now. My partner and I have just had a baby so things are going to be a bit slower just now for a wee while.

I'm going to close this PR as the request is pretty much covered in other issues. I would normally welcome a PR but to be honest, I have a backlog I need to get through first. I will try and take a look at this at some point but I can't dedicate time to it just now sorry.

I'm targetting this weekend to get a new version out so might be able to take a better look at it then and will update in the JWT claims issue if this is the case. Cheers

@Sephster Sephster closed this as completed Apr 7, 2020
@Richard87
Copy link
Author

of course, no problem, take your time, I have solved it temporarily, and congratulations!

(for future records, "finalizeScopes doens't work, because it doesn't have access to the authCode or the authorization session cookies etc)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants