Apigee Edge is our strategic platform of choice for API management. However for enterprise identity management we have azure AD as our strategic platform. We are trying to bring these two together

We have a bunch of public facing APIs exposed via Apigee edge (exclusively for our external clients).

The question is how do i use Apigee Edge just as a resource server and use Azure Active Directory for authentication and token issuance. Are there standard integration plug-ins available to do that?

Any help with regards to where to get started would be useful. I have looked at few other posts in the community but it is unclear how to get started and what exactly is required to achieve this integration.

1 Answer

Apigee Edge can integrate with external identity providers in a number of ways.

You said you want to

use Apigee Edge just as a resource server and use Azure Active Directory for authentication and token issuance.

And here I have a question: what kind of tokens are you talking about? There are things such as "identity tokens", aka id_tokens. These are tokens in JWT format which are issued by Open ID Connect identity providers to identify individuals. Azure Active Directory is one such system that can issue such tokens. Others include Google Signin, Ping Identity, Salesforce.com, and there are more.

These ID tokens are useful for collecting a bunch of metadata about a person, signing it, and then providing it to an "audience" or an app. This is the way that a mobile app might learn of the email address of the user, or the surname, or the group affiliation, or some other metadata that the Identity provider might choose to assert about the subject (person). Because the identity provider signs the JWT with its private key, any party can verify the signature with the public key, and subsequently can rely on or trust the assertions in the token.

Access tokens are different. Access tokens can come in various formats, including JWT or just :opaque: tokens (usually a random string of alphanumeric digits), but the format is not the difference I am talking about here. The key difference is the purpose of the token, what it is used for. The access token is checked by the resource server (often Apigee Edge) in order to verify that the {user, app} tuple that is requesting a resource, should be permitted to request the resource.

So which kind of token do you want Azure AD to issue?

With an access token, the resource server might enforce a simple authorization check - "is this token valid?" - or it may be much more nuanced than that. For example, is this token valid for the given verb+resource path? Does this token have the required scope (READ ACCOUNT, DELETE PROFILE, UPDATE BALANCE, etc)? Is this token within the rate limits prescribed for this API? Apigee Edge is good at all of these sorts of nuanced checks, and in order to perform such checks, Apigee Edge needs to "know" about the token. That means the token must be present in the Apigee Edge store.

Apigee Edge "knowing" about a token is not the same as Apigee Edge issuing the token. Obviously Apigee Edge ⟪knows⟫ about a token when Apigee Edge itself issues the token; and this is the normal case, and is probably the case you see in most of the various examples published here on community or in youtube videos and apijam handson exercises and so on. But it is also possible for Apigee Edge to ingest a token generated by a third-party system, like Azure AD, and then store the token, so that it can be used for all the nuanced checks I described previously. In fact, importing a token is the topic of a community question I answered two weeks ago.

On the other hand it is possible to allow Apigee Edge to check (verify) an ID token and exchange that for a "native" access token. This may be easier and smoother. In this approach, the user employs the app, goes through an OpenID Connect signin, the app receives the id_token from the IDP, and then the app can send the id_token to Apigee Edge; Apigee Edge verifies the token, and then issues a time-limited access token generated by Apigee Edge.

Either importing an access token generated by Azure AD or using Apigee Edge to generate an access token from an inbound id_token, would require the application identifier (aka consumer key, aka client id) to be synchronized across Azure AD and Apigee Edge. Fortunately Apigee Edge allows import of a client id / secret pair via API.

verify the {user:app} tuple (as you put it) that is requesting a resource should be permitted to request the resource.

I understand the need for Apigee to "know" about the token. And we would rather have Apigee "know" the details of a token as opposed to issue the token. There are reasons specific to the domain that we operate which aligns better with use of Azure Active Directory (as a centralised identity server and token dispensary).

Is there an alternative approach to importing client id, key (from Azure AD) to Apigee. If we could, we would prefer to avoid the sync between the two systems (Azure Ad and Apigee for client id and key reconciliation).

There is also a need to expose the our identity and claims management service (which is a wrapper around Azure AD OAuth endpoints) to be exposed via Apigee so that external clients will always ever use APIs exposed via Edge for all things functional and non-functional.

What is unclear at this point is how would we get the exposed client facing identity proxy to internally

hook into Azure AD,

validate the (client) credentials,

issue access_token based on a set on pre-conditions,

return it to apigee

exchange it for an :opaque: token (while retaining the token in apigee's token store).

I understand the need for Apigee to "know" about the token. And we would rather have Apigee "know" the details of a token as opposed to issue the token.

ok, but let's clarify just a bit. If Apigee Edge validates *opaque* tokens, then Apigee Edge needs to "know" about the token. If Apigee Edge is used to validate a JWT, that's a federated token, and Apigee Edge just needs access to the public key that matches the private key used by Azure.

If Apigee Edge validates the token, there are two possibler outcomes: (1) the token signature is valid. (2) The token signature is not valid. The unhappy path, invalid token, is easy. Apigee Edge just rejects the call. For the happy path, probably you will want Apigee Edge to do some additional validation of the *contentS* of the token. And a great example of this would be; validate the client_id.

The client_id in the token will be inserted there by Azure AD. Apigee Edge can validate that client_id if you have imported that client credential into Apigee Edge.

Is there an alternative approach to importing client id, key (from Azure AD) to Apigee. If we could, we would prefer to avoid the sync between the two systems (Azure Ad and Apigee for client id and key reconciliation).

The import of client credentials, or at least client_id, allows Apigee Edge to validate the client_id in its normal fast-path mechanism. The Edge MP will read from the keystore, and this is a fast operation (cost = ~4ms), and the results are cached, which means subsequent validations cost much less than 1 ms. This approach is time-tested, and allows scale to 10's of 1000's of transactions per second.

If you don't follow this path, the only other alternative I see is to call out to Azure AD, synchronously, to validate the client_id each time. This will be ~100ms for each call, and ... it will not scale like what I just described.

There is also a need to expose the our identity and claims management service (which is a wrapper around Azure AD OAuth endpoints) to be exposed via Apigee...

This sounds like a separate but related issue? Maybe we can resolve one thing at a time.

I like the idea of sharing the public key (with Apigee) that matches the private key used by Azure.

Couple of questions around that

1. Just so i understand, if we do that, then Apigee will be able to validate the signature of the federated token (JWT) that was issued by Azure AD in the first place?

2. Using an "opaque" token (which in my head is a different from the one issued by Azure AD) would mean that Apigee Edge extracts claims from the Azure AD JWT, creates a new token i.e "opaque" token and then pass this token to the client. When the client makes an API request - Apigee would then unpack the opaque token and validate the client_id in its claims against the client_id that it imported from Azure AD.

Do you expect Edge to then pass the original JWT (issued by the Azure AD) to the actual API server or the "opaque" token?

You are right in proposing that we would want Apigee Edge to do additional validations of the "contents" of the token - precisely the validation of client_id, among others.

Now that you mention the latency involved in using Azure AD, i am inclined to go with the option that you propose - import client_ids in Apigee. Would this happen via a custom sync service? Is there any reference i can use to start formulating a view on what this would look like?

Lastly, your summary of steps in the flow is exactly what we require - you mention it will be 5 policies or so - please would you be able to provide more details on what those policies are and how to string them together (if there is an existing post or a wiki page that would be great).