locked
OAuth in API Management RRS feed

  • Question

  • Hi,

    Can somebody validate my understanding of the current OAuth implementation in API Management?

    • Configuring an OAuth Server in APIM only facilitates the developer portal experience.
    • APIM doesn’t restrict access to the backend API by using the configured OAuth Server in APIM
    • APIM can restrict access to the backend API by requiring a valid JWT token (by using the policy)
    • Client applications need to obtain an OAuth Access Token directly from the OAuth server and pass this as a ‘bearer token’ to APIM in the request header.
    • The Backend API can/must validate the provided Access Token itself against the OAuth Server.

    Is this correct or am I missing something?

    Thanks!

    Edward
    Monday, October 5, 2015 11:21 AM

Answers

  • Hi Edward,

    You are correct (and we had very similar questions about this when we started).

    Your OAuth service is a completely separate entity from APIM, and configuring an OAuth server in APIM only facilitates the developer portal experience.  Specifically, APIM will render a dropdown for obtaining authorization in the console for an operation. Depending on the OAuth flow you support, APIM will handle redirecting to the Authorization endpoint on your OAuth server, where you can authenticate the user and then show a consent UX ("Would you like the "Developer console" to access your data...").  Note that you'll need to register the developer console as an application with your OAuth service.  

    Outside of the portal, client apps will need to obtain an access token directly from your OAuth service, and then provide it (along with a subscription key) to APIM when making calls to the API.

    The subscription key will be supplied as part of the query string or as part of a header (normally named ocp-apim-subscription-key but you can rename it via the management API).  The OAuth access token will be submitted as part of the standard Authorization header.

    In the proxy, you can configure a validate-jwt policy to ensure that the incoming JWT emitted from your OAuth service is properly signed, has the right issuer, audience, and any required claims.  

    The proxy will include the JWT when calling your backend API (APIM will forward headers to your backend), and you can choose to re-validate the JWT or ignore it.  For our implementation, our backend services also verify the JWT signature (I'm not yet ready to remove the JWT validation from our backend API and completely rely on APIM), but you can choose whether or not you want to do anything in your backend.  

    We've implemented an OpenID connect configuration endpoint in our OAuth service, which exposes the public keys used to verify the signature of the JWT.  We've configured the validate-jwt policy to obtain the issuer and signing keys from this OpenID connect endpoint, so that we don't have to hardcode signature keys into the policy.  Our backend services also use this configuration endpoint to verify the signature of the incoming JWT.

    Hope this helps!

    Monday, October 5, 2015 4:27 PM
  • Hi Edward, you are correct on every statement except the last one. If you use Validate JWT policy, then the backend API does not necessarily need to authenticate incoming request against the OAuth server. 
    Monday, October 5, 2015 4:28 PM

All replies

  • Hi Edward,

    You are correct (and we had very similar questions about this when we started).

    Your OAuth service is a completely separate entity from APIM, and configuring an OAuth server in APIM only facilitates the developer portal experience.  Specifically, APIM will render a dropdown for obtaining authorization in the console for an operation. Depending on the OAuth flow you support, APIM will handle redirecting to the Authorization endpoint on your OAuth server, where you can authenticate the user and then show a consent UX ("Would you like the "Developer console" to access your data...").  Note that you'll need to register the developer console as an application with your OAuth service.  

    Outside of the portal, client apps will need to obtain an access token directly from your OAuth service, and then provide it (along with a subscription key) to APIM when making calls to the API.

    The subscription key will be supplied as part of the query string or as part of a header (normally named ocp-apim-subscription-key but you can rename it via the management API).  The OAuth access token will be submitted as part of the standard Authorization header.

    In the proxy, you can configure a validate-jwt policy to ensure that the incoming JWT emitted from your OAuth service is properly signed, has the right issuer, audience, and any required claims.  

    The proxy will include the JWT when calling your backend API (APIM will forward headers to your backend), and you can choose to re-validate the JWT or ignore it.  For our implementation, our backend services also verify the JWT signature (I'm not yet ready to remove the JWT validation from our backend API and completely rely on APIM), but you can choose whether or not you want to do anything in your backend.  

    We've implemented an OpenID connect configuration endpoint in our OAuth service, which exposes the public keys used to verify the signature of the JWT.  We've configured the validate-jwt policy to obtain the issuer and signing keys from this OpenID connect endpoint, so that we don't have to hardcode signature keys into the policy.  Our backend services also use this configuration endpoint to verify the signature of the incoming JWT.

    Hope this helps!

    Monday, October 5, 2015 4:27 PM
  • Hi Edward, you are correct on every statement except the last one. If you use Validate JWT policy, then the backend API does not necessarily need to authenticate incoming request against the OAuth server. 
    Monday, October 5, 2015 4:28 PM
  • Thanks!
    Monday, October 5, 2015 5:48 PM
  • Thank you  for your detailed explanation!

    Cheers,

    Edward

    Monday, October 5, 2015 5:51 PM
  • Hi Edward, you are correct on every statement except the last one. If you use Validate JWT policy, then the backend API does not necessarily need to authenticate incoming request against the OAuth server. 
    In my recent experience with the <validate-jwt policy, I can confirm that apim is NOT making requests to my auth server (https://github.com/panva/node-oidc-provider, not AAD) when testing a JWT. It only decrypts it locally and compares the <required-claims>
    Tuesday, May 21, 2019 8:10 AM
  • Ben Lambert - 

    With respect to your statement - "We've configured the validate-jwt policy to obtain the issuer and signing keys from this OpenID connect endpoint, so that we don't have to hardcode signature keys into the policy.  Our backend services also use this configuration endpoint to verify the signature of the incoming JWT."

    I am struggling to implement Validate JWT policy at APIM and it gives an error saying Signature validation failed. Unable to match keys.

    Basically - I am trying to implement - Protecting APIs using OAuth 2.0  with Azure AD and API management by following this article.

     

    I have successfully created all the steps defined like App registrations (Client app and back end app), Granted permissions, Enabled Oauth 2.0 etc. 

    While testing it from the developer portal, I have selected "Authorization Code" in the drop down which gave me bearer token as well. So far so good.

     

    What I am trying to do next is Configure a JWT validation policy to pre-authorize requests at APIM Level.

     

    By going to this site, I copied  the Policy sample for "Azure Active Directory B2C token validation "section and Changed the params accordingly as shown below.

     

    <inbound>

    <base />

    <validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">

    <openid-configurl="https://login.microsoftonline.com/tfp/mytenant.onmicrosoft.com/B2C_1_myapp/v2.0/.well-known/openid-configuration" />

    <required-claims>

    <claim name="aud">

    <value>{APP-id of the back end App of App registration}</value>

    </claim>

    </required-claims>

    </validate-jwt>

    </inbound>

     

    When I try to call the backend API (GetSpeakers) in the Demo Conference API within APIM, I get the following error.

     

    On error

    validate-jwt (98 ms)

    {     "message": "JWT Validation Failed: IDX10501: Signature validation failed. Unable to match keys: \nkid: 'BB8CeFVqyaGrGNuehJIiL4dfjzw', \ntoken: '{\"typ\":\"JWT\",\"alg\":\"RS256\",\"x5t\":\"BB8CeFVqyaGrGNuehJIiL4dfjzw\",\"kid\":\"BB8CeFVqyaGrGNuehJIiL4dfjzw\"}.{\"aud\":\"api://ecef-ee03-4276-826c-1ef2189aa\",\"iss\":\"https://sts.windows.net/e72d-da0-48d-9e9f-94dce8/\",\"iat\":1573813446,\"nbf\":1573813446,\"exp\":1573817346,\"acr\":\"1\",\"aio\":\"AVQAq/8NAAAA/tlSxk+kizD/qTKXC7WTaeLJXMevzs9OLtV+r+0tQ3pQZ9hOOJTRSJLcnrxolVsg2l35qHfBxSIUpmb2J/uMERGN8EdDG4m/9OPh8FehC1M=\",\"amr\":[\"pwd\",\"mfa\"],\"appid\":\"522bb8-ff96-4954-ad39-1d3e788e0e\",\"appidacr\":\"1\",\"family_name\":\"Jerry\",\"given_name\":\"Mathew\",\"ipaddr\":\"162.221.104.64\",\"name\":\"Mathew \",\"oid\":\"58a46f-bdb0-42fd-8959-bf4c85d5\",\"onprem_sid\":\"S-1-5-21-10781533-17571266-682003330-17465572\",\"scp\":\"My-API-Scope\",\"sub\":\"tOwD92q39XpNNw2zD_-IwOYJd9W7D-195HDhJzmUI\",\"tid\":\"e754d-d5a0-488d-9e9f-949ece8\",\"unique_name\":\"GF0000910@abc.com\",\"upn\":\"GF00000910@abc.com\",\"uti\":\"aJBNjrnDjUOEVqWDFcMXAA\",\"ver\":\"1.0\"}'.." }

     

    I have been struggling for the past 2 days. Can you help me on what went wrong ? 

    Thanks in Advance!

    -Mathew James

    Friday, November 15, 2019 11:35 AM