Is there a way to setup apigee to use external authentication server

mmt
Bronze 1
Bronze 1

Is there a way to setup apigee to use external authentication server, to better explain the situation:

  • we generate a token from an app (test.app.com/services/oauth2/token)
  • we send this token with the request to the apigee endpoint
  • the apigee should call (test.app.com/services/oauth2/introspect) with authentication header (basic) and with body containing the token to verify it.

Im fairly new in apigee and have not seen similar implementations in my search

1 1 229
1 REPLY 1

Yes you can do that .

I assume the generate and send steps, ... you have a clear understanding of how to do that. 

For the "call the introspect endpoint" I have some comments. 

First, if I were doing this I would use ServiceCallout - this is a policy that is included in Apigee and enables you to call out to external services.  Exactly your scenario.  With the ServiceCallout policy you can specify the verb, path, headers, and payload/body you want to send out.  So your ServiceCallout might look like this: 

<ServiceCallout name='SC-Introspect-Token'>
  <Request variable='outboundRequest'>
    <Set>
      <Headers>
        <Header name='Authorization'>Basic {basic-auth-blob}</Header>
         <Header name='content-type'>application/x-www-form-urlencoded</Header>
     </Headers>
     <FormParams>
       <FormParam name='token'>{variable-containing-token-from-client}</FormParam>
     </FormParams>
      <Verb>POST</Verb>
      <Path>/services/oauth2/introspect</Path>
    </Set>
  </Request>
  <Response>calloutResponse</Response>
  <HTTPTargetConnection>
    <SSLInfo>
      <Enabled>true</Enabled>
      <IgnoreValidationErrors>true</IgnoreValidationErrors>
    </SSLInfo>
    <Properties>
      <Property name='success.codes'>2xx, 4xx, 5xx</Property>
    </Properties>
    <URL>https://test.app.com</URL>
  </HTTPTargetConnection>
</ServiceCallout>

To get the basic-auth-blob you need to ... yknow... base64 encode the username/password pair.  You can generate that blob from the constituent parts in Apigee via the BasicAuthentication policy using the Encode operation, OR via AssignMessage/AssignVariable and the encodeBase64 function, or you can read that blob from some configuration source, like a KVM or a properties file or even hard-code it there in the configuration for the ServiceCallout policy (not recommended). 

The variable-containing-token-from-client is probably something you extract from the Authorization header in the inbound request.  Get that token into the variable with ExtractVariables using the Header element, or with an AssignMessage/AssignVariable that uses the substring function to strip off the "Bearer " prefix (don't forget the space). 

Attach this policy to your Request flow somewhere in the Apigee configuration. You will need to follow up that policy with something that inspects the calloutResponse to see if the token is suitable for its intended use. 

Second thing, in my experience these access tokens are usually JWT. You can verify a JWT directly within Apigee without callout out to an introspection endpoint. Do that with the VerifyJWT policy.  It will check a signed JWT for expiry, the correct signature, and the right algorithm, etc. You can subsequently check the payload for the presence of the right scope member, or whatever else you want to check for.  This would avoid a remote call to the introspection endpoint for each authorization check.  It would likely be faster. But of course calling out to the introspection endpoint is fine. 

If you have lots of calls with the same token you might want to cache the results of the check (either via the ServiceCallout or VerifyJWT) using the PopulateCache policy. You'd then need to use LookupCache to check for a cache entry before doing the ServiceCallout or VerifyJWT.