oauth
51 TopicsBasic OAuth concept and OAuth with F5 solutions
In my previous article [Overview of API Access Control and implementing API key access control with BIG-IP APM] , I explained the ‘API-Key based Access Control’ method and we could see how a user implements it easily and securely using BIG-IP APM. However, although the ‘API-Key’ method has its advantages, it also has some limitations when we use it in the enterprise-grade API access control implementation. Problems of the API-Key Access Control API Key compromise Although some improved API-Key systems can set an expiration time for API keys, the expiration time for keys has to be set for a longer time such as weeks, months, or a year. This is because the issued key should be configured manually to API clients or API G/W or API endpoints. This manual process requires extra operational overhead, thus it is normally recommended to use a long expiration time for keys. However, a longer expiration time may bring security problems as well. Let’s say the issued key is stolen without recognition by the organization, then what happens? Since the key’s expiration time might be set to months or a year, the attacker who stole the key can access the corporate resources until the key reaches its expiration time, a year in the worst case. 3rd party integration Since the API-key method doesn’t have any pre-defined flow or format of the key, it could be challenging to integrate the enterprise’s API system with 3rd party client applications. For example, if Google, AWS, Dropbox, and Open banking services were to provide all different API access control methods, application developers would need to create all different modules for their applications to integrate each service. This is not a scalable solution to integrating the organization’s APIs with other 3rd party applications. OAuth 2.0 An OAuth 2.0 standard protocol was introduced in 2012 to solve these challenges and was defined in RFC6549. It was designed to implement API access control and is one of the most widely adopted methods for API access control purposes. The common misunderstanding of an OAuth is that it is considered an ‘Authentication protocol’. But it’s not an authentication protocol. While OAuth can provide authentication capability with its well-known extension – ‘OIDC(OpenID Connect)’, OAuth itself can work without OIDC and it primarily solves the access delegation problem. If a user wants to delegate third-party application access to their Gmail profile, OAuth can solve this. Many experts explain an OAuth with an example of a hotel key card. Once the key card is issued to the user, the room doesn’t authenticate the user but rather the valid key card. An OAuth works like a hotel key card, thus it is not an authentication protocol. In an OAuth implementation, a token performs the same role as a ‘key’ of the ‘API-Key method’. One of the biggest technical advantages of OAuth is to provide centralized token management, user authentication, and a privilege consent process. This centralized policy management can help an enterprise to expand their API network and organizations more easily integrate their APIs with external applications. An OAuth is a big topic and we can not cover all the details of it in this short article. However, there are some important terminologies and concepts to understand the overall OAuth flow. OAuth roles OAuth standard introduces 4 different roles in a typical OAuth flow. Resource Owner(RO): RO indicates the person who owns the resources. If a fintech app tries to access a user’s banking account, the user is the resource owner(RO). Resource Server(RS): RS is the place to host protected resources. In the above banking example, the server which hosts the banking API is the resource server and the banking API itself is the resource. OAuth Authorization Server: OAuth AS is the centralized system to manage and issue the access token to OAuth clients. OAuth Client Application: The OAuth client indicates the application which wants to access a resource on behalf of the resource owner. In the banking example, the fintech app is the OAuth client. OAuth grant types OAuth grant types define how an OAuth client can obtain a grant from a resource owner to access their resources on their behalf. An OAuth 2.0 defines 4 different grant types. 1) Authorization Code Grant The application(=client) obtains the ‘authorization code’ first from the authorization server and the client exchange the code for an access token. This allows the access token to be never exposed to the resource owner’s user-agent. 2) Implicit Grant Optimized for in-browser JS clients. Instead of an authorization code, an access token is issued immediately without client authentication. 3) Resource Owner Password Credential Grant Username and password are used instead of an authorization code to obtain an access token. Should only be used for highly trusted clients or when other types are not available. Username and password are only used to get an access token and are not stored. 4) Client Credential Grant The client supplies its own credentials to get an access token. Support OAuth in F5 solutions Since OAuth is a key protocol for the enterprise-grade API implementation, F5 solutions support OAuth widely as well. F5 BIG-IP APM and NGINX Plus support various OAuth roles and grant types. Organizations can build their own secure OAuth framework using F5 solutions. Integrating with partner solutions Since OAuth is a standard protocol, one of its strong benefits is to be supported by different vendor solutions. While F5 provides all types of OAuth roles in our product portfolio, we also provide tight integrations with our partner’s platforms, this includes leading vendors of IDaaS solutions – Microsoft Azure AD, Okta, and Ping. F5 BIG-IP APM has built-in OAuth configuration sets for these vendors already, so customers easily can configure their BIG-IP APM device to work with these vendor’s solutions. That means a customer can deploy Microsoft Azure AD or Okta or Ping Identity as their OAuth Authorization Server, and they can configure the BIG-IP APM and NGINX Plus API Gateway as their OAuth Resource Server. Both BIG-IP APM and NGINX Plus can work with those IDaaS vendor’s solutions to build an enterprise-level of OAuth for an organization. Summary An OAuth is an essential component to implement API access control to protect the enterprise’s API endpoints. However, the OAuth standard includes different roles, grant types, and extensions. Because of its complexity, some organizations may have some difficulty adopting the technology. F5 solution can help an organization adopt OAuth more easily. For example, F5 supports different roles of OAuth with multiple solutions – BIG-IP APM and NGINX Plus API Gateway. A customer can build their own OAuth network using F5 solutions only or they also can configure our solutions to work with industry-leading IDaaS vendors such as Microsoft, Okta, and Ping Identity. With all the flexibility and powerful policy management capabilities of the F5 solution, an organization can implement and operate its OAuth systems more effectively.3.8KViews6likes1CommentRequest and validate OAuth / OIDC tokens with APM
BIG-IP APM is able to request and validate OAuth2.0 and OpenID Connect tokens. It can act as Client, Resource Server and Authorization Server. In this article, I cover the use cases where APM acts as Resource Server (validating the tokens) and Client (requesting the tokens). 1. The tokens : Access Token: this is the Oauth2.0 token (access_token). It is used for Authorization and has to bevalidated by the Resource server. This Resource Server will contact the Authorization server for validation (Out of Path validation - External) Access Token can be either OPAQUE or JWT ID Token: this is the OpenID Token (id_token).It is used by the client onlyin order to know you use the resource owner. For instance, when you see you name and your picture on the top right corner of an app, this comes from the ID_Token. This token is not user/validated by the Resource Server ID Token is JWT only 2. OPAQUE vs JWT tokens : JWT: Decodable Encryptable Can be validated against a preconfigured JWKS in-box or externally OPAQUE: Not decodable (opaque) Proprietary format, might be any length, and must be unique Must be validated in out-of-path HTTP request to the originating provider (the Authorization Server) 3. Token validation : OAuth Scope agentis used to validate anAccess Token either against aninternalJSON web key set (JWKS) if the Access Token isJWTvia an APM provider configuration (Azure AD uses JWT only) orexternallyvia HTTPS if the Access Token isOpaque. JWKS is faster because we don't have an extra HTTP transaction. Oauth Scope agentis used when APM is RS and the request from the client (APM or mobile app) has a authorization bearer header. Either with Opaque (External)or JWT token (Internal). With Opaque token, if the RS needs more information about the user, it needs to request anOpenID Connect UserInfoby presenting theaccess_token to the AS. The opaque scope provides with several information but it depends of the AS. For Google, an OIDC userInfo is needed to get the First and Last names. 4. Token Request : Oauth Client agentis used to request theAccess token and id_tokenwhen APM is deployed asOauth Client. To do so, 2 grant types are available (Code and password) WithAuthorization code grant, the Client agentexchangesan Authorization code for an access_token code + id_token (if OIDC used). When the Oauth Client gets the access_token (and id_token), theOauth scope agent validatesthem.3.6KViews5likes3CommentsJSON Web Token (JWT) Parser
Problem this snippet solves: This feature is now native in v13.1 and it is strongly recommended you implement the native solution instead. This code is left only as an example for future use cases, it should not be used for JWT handling because there is no signature validation. This code parses a JWT (JSON Web Token) received by a Big-IP acting as an OAuth client and creates session variables for the JSON parameters in the header and payload. Example use cases might include Azure AD B2C or Azure AD Enterprise integration. This iRule does not perform signature validation. Code from the "Parse and Set Session Variables" section down could be easily harvested for other JSON parsing use cases that do not need the JWT decoding. How to use this snippet: Attach this iRule to the virtual server receiving the JWT that is configured for OAuth. Inside the VPE after the OAuth Client agent add an iRule agent with id jwt-parse. This iRule will set several variables including: session.oauth.jwt.last.header session.oauth.jwt.last.payload session.oauth.jwt.last.signature In addition it will create a session variable for each parameter in the header and payload in the following syntax. session.oauth.jwt.header.last.* session.oauth.jwt.payload.last.* You can then call these session variables elsewhere. Code : when ACCESS_POLICY_AGENT_EVENT { if { [ACCESS::policy agent_id] eq "jwt-parse" } { #log local0. "JWT-Parse: Started" #Get the JWT set jwt [ACCESS::session data get -secure session.oauth.client.last.id_token] #log local0. "JWT-Parse: JWT Received - jwt is $jwt" #Separate the header, payload, and signature set jwt_header [getfield $jwt "." 1] ACCESS::session data set session.oauth.jwt.last.header $jwt_header #log local0. "JWT-Parse: Header extracted - jwt_header and session.oauth.jwt.last.header are $jwt_header" set jwt_payload [getfield $jwt "." 2] ACCESS::session data set session.oauth.jwt.last.payload $jwt_payload #log local0. "JWT-Parse: Payload extracted - jwt_payload and session.oauth.jwt.last.payload are $jwt_payload" set jwt_signature [getfield $jwt "." 3] ACCESS::session data set session.oauth.jwt.last.signature $jwt_signature #log local0. "JWT-Parse: Signature extracted - jwt_signature and session.oauth.jwt.last.signature are $jwt_signature" #Base 64 decode the header and payload #Fix encoding issues in header set jwt_header_modified $jwt_header set tail [string length $jwt_header_modified] if {$tail % 4 == 2} { append jwt_header_modified {==} } elseif {$tail % 4 == 3} { append jwt_header_modified {=} } #log local0. "JWT-Parse: Header encoding fixes complete - jwt_header_modified is $jwt_header_modified" #Fix encoding issues in payload set jwt_payload_modified $jwt_payload set tail [string length $jwt_payload_modified] if {$tail % 4 == 2} { append jwt_payload_modified {==} } elseif {$tail % 4 == 3} { append jwt_payload_modified {=} } #log local0. "JWT-Parse: Payload encoding fixes complete - jwt_payload_modified is $jwt_payload_modified" #Base64 decode set jwt_header_modified [b64decode $jwt_header_modified] #log local0. "JWT-Parse: Header Base 64 decoded - jwt_header_modified is $jwt_header_modified" set jwt_payload_modified [b64decode $jwt_payload_modified] #log local0. "JWT-Parse: Payload Base 64 decoded - jwt_payload_modified is $jwt_payload_modified" #Parse and Set Session Variables #Remove JSON characters set jwt_header_modified [string map {\{ {} \} {} \[ {} \] {} \" {}} $jwt_header_modified] #log local0. "JWT-Parse: Header JSON Characters removed - jwt_header_modified is $jwt_header_modified" set jwt_payload_modified [string map {\{ {} \} {} \[ {} \] {} \" {}} $jwt_payload_modified] #log local0. "JWT-Parse: Payload JSON Characters removed - jwt_payload_modified is $jwt_payload_modified" #Split into field/value pairs set jwt_header_modified [split $jwt_header_modified ,] #log local0. "JWT-Parse: Header Fields split - jwt_header_modified is $jwt_header_modified" set jwt_payload_modified [split $jwt_payload_modified ,] #log local0. "JWT-Parse: Payload Fields split - jwt_payload_modified is $jwt_payload_modified" #Set APM session variables for each header parameter foreach parameter $jwt_header_modified { set variable_name [getfield $parameter ":" 1] set variable_value [getfield $parameter ":" 2] ACCESS::session data set session.oauth.jwt.header.last.$variable_name $variable_value #log local0. "JWT-Parse: Header session variable set - session.oauth.jwt.header.last.$variable_name is $variable_value" } #Set APM session variables for each payload parameter foreach parameter $jwt_payload_modified { set variable_name [getfield $parameter ":" 1] set variable_value [getfield $parameter ":" 2] ACCESS::session data set session.oauth.jwt.payload.last.$variable_name $variable_value #log local0. "JWT-Parse: Payload session variable set - session.oauth.jwt.payload.last.$variable_name is $variable_value" } } } Tested this on version: 13.03.5KViews2likes14CommentsAPM as Oauth Authorization server
I am trying to figure out how to setup APM as an Authorization server for ESRI portal. Any ideas you could provide would be appreciated. Current F5 Setup: Running version 14.1.4.4 I have configured Oauth using guided configure and OAuth Authorization server Oauth profile: Is not using Opaque Token as I read that can cause issues but I am usingsupport for JWT and OpenID connect enabled. Client Application using OpenID Connect and Secret I have tried different scopes but not exactly sure what I need to define and what should be sent as part of default openID. Single Virtual server that has Access profile tied to it Access profile with Login page, AD auth and Oauth_authorization. Profile has Oauth profile tied to it. ESRI setup: I have populated Client ID and secret from client application created on F5 side I am using default scopes (openid email and profile) Other information: When I try to connect I get did not receive user profile parameter from the provider If I connect ESRI to google as the providor I have no issues so it is something I am missing on my APM config. I have tried a bunch of the configuration guides but not sure what I am missing. Want to be able to use openid via oauth version 2.0 that will use on prem Active directory idenity to login to a cloud application. Questions: Is there something obvious that I am missing in order for the service providor to be able to get user profile information from apm? From what I read you need to defind scopes but do you need to defind scopes for openid or profile? If so what do you use for the value on those scopes? Thanks NolanSolved3.3KViews0likes4CommentsUsing OpenID Connect to authenticate users
Hello all, I want to use OpenID Connect to authenticate my users before gaining access to one of my application. I want to use my bigip as OpenID Provider (ie: the entity that authenticate the users) . My issue is the following: The OpendID provider (my bigip) never provides me with a ID Token. All I have is an “Access Token” and a “Refresh Token” but no “ID Token”. Below is a description of my lab: resource owner: ip address 10.10.255.1 bigip OpenID Provider: virtual server ip 10.10.255.221 (see below for the access policy) *The agents are left with their default values. Client: I user openid debugger (https://oidcdebugger.com/) in order to request the authorization code. Then I request the Tokens using an html code. I do the following for testing : I request the authorization code from the authorization server (ie my virtual server) . For this I use openID Connect debugger to construct the request for me. Here is the request that I send : ? client_id=e1111098ccff5f81859f9fc83eaa000c29267803efc0bb5b & redirect_uri=https://oidcdebugger.com/debug & scope=openid myscope & response_type=code & response_mode=form_post & state=toto & nonce=7r8saarltr After sending this request I enter my credentials (in the logon agent), I click on authorize then the virtual server correctly redirects me to: https://oidcdebugger.com/debug code=cae85f6fd33c6b27f56f536b6fd9af2ca0fc78e69ac3d13799533c143b38b4ac&state=toto” I now have a correct authorization code that I can exchange for an “access token” AND a “ID Token” . I then send a POST to get the access and ID Tokens using the following HTML code : *note the presence of the “openid” in the scope parameter. However, this is what I get from the authorization server (see in the comment) : -> I have No “ID TOKEN” ☹ Could you please help me configure my access policy so that it supports OpenID Connect and sends me an “ID Token” ??2.8KViews0likes8CommentsAPM JWT Multiple Providers NOT WORKING
Dear F5 community, Using F5 APM 16.1.3 (as an oauth resource server) I am trying to implement a per-request policy that will verify the signature of JWT tokens sent by the client. These JWT tokens can be issued from two differents issuer (Azure AD or STS). I am able to verify JWT tokens for each provider seperatly using a dedicated "JWT provider" with only one Provider attached. When using 2 providers as follow I got following error message: WWW-Authenticate:Bearer error="invalid_token",error_description="Issuer Mismatch : Claim issuer= https://sts.windows.net/ Provider issuer=https://login.microsoftonline.com/v2.0" Based on F5 doc below, the built-in object supports having multiple JWT providers https://clouddocs.f5.com/cli/tmsh-reference/v15/modules/apm/apm_oauth_jwt-provider-list.html Configuration is pretty simple: - 1 Access Policy with "Allow" all ending - 1 Per-Request Policy with "OAuth Scope" set to "Internal" with the "jwt-allowed-providers-list" I guess It is most likely a bug. Anyone was able to make it work with multiple JWT providers ? I can workaround this by parsing the JWT payload, then determining the issuer and based on the issuer make two branches in the VPE: - first branch with the "oauth scope A" that will validate the token using JWT-Provider-A - second branch with the "oauth scope B" that will validate the token using JWT-Provider-B Thanks2KViews1like5CommentsProtecting API Access with BIG-IP using OAuth
As more organizations use APIs in their systems, they've become targets for the not-so-good-doers so API Security is something you need to take seriously. Most APIs today use the HTTP protocol so organizations should protect them as they would ordinary web properties. Starting in v13, BIG-IP APM is able to act as an OAuth Client, OAuth Resource Server and OAuth Authorization Server. In this example, we will show how to use BIG-IP APM to act as an OAuth Resource Server protecting the API. In our environment, we’ve published an API (api.f5se.com) and we’re trying to get a list of departments in the HR database. The API is not natively protected and we want APM to enable OAuth protection to this API. First, let’s try an unauthenticated request. You can see we get the 401 Unauthorized response which is coming from the BIG-IP. In this instance we’re only sending 3 headers, Connection (close), Content Length (0) and WWW Authenticate (Bearer), indicating to the client that it wants Bearer Token authentication. So we’ll get that authorization and a new access token. Here the Getpostman.com (Postman toolchain for API developers) is preconfigured to get a new access token from the OAuth authorization server, which is a BIG-IP. We will request the OAuth token and will need to authenticate to the BIG-IP. After that, we get an authorization request. In this case, BIG-IP is acting as an Authorization server and is indicating to the resource owner (us) that there is a HR API application that wants to use certain information (about us) that the authorization server is going to provide. In this case, it is telling us that the resource server wants to get scope api-email. We’ll click Authorize and now we have our auth token and is saved in the Postman client. Within the token properties we see that it expires in 300 seconds, it is a Bearer token and the scope is api-email and we get a refresh token as well. Now we can add this token to the header and try to make a request again. And this time, we get a much better response. We get a 200 OK, along with the headers of the application server. We’ll click on the Body tab within Postman, we’ll see the XML that the API has returned in response to the query for the list of departments that are available. There were no cookies being returned by the server if you were wondering about that tab. In the Headers tab we see the Authorization header that was being sent and the content of the Bearer token. A simple way to easily protect your APIs leveraging OAuth 2.0 Resource Server capabilities in BIG-IP. Special thanks to Michael Koyfman for the basis of the content and check out his full demo here. ps Related: Web API – Security Review – How to Hack an API and Get Away with It API Security Testing – How to Hack an API and Get Away with It API Reference - DevCentral Wiki1.6KViews0likes2CommentsUsing NGINX Controller API Management Module and NGINX App Protect to secure financial services API transactions
As financial services APIs (such as Open Banking) are concerned primarily with managing access to exposed banking APIs, the security aspect has always been of paramount importance. Securing financial services APIs is a vast topic, as security controls are distributed among different functions, such as user authentication at the Identity Provider level, user authorization and basic API security at the API Gateway level and advanced API security at the WAF level. In this article we will explore how two NGINX products, Controller API Management Module and App Protect, can be deployed to secure the OAuth Authorization Code flow which is a building block of the access controls used to secure many financial services APIs.. Physical setup The setup used to support this article comprises of NGINX Controller API Management Module, providing API Management functions through an instance of NGINX API Gateway and NGINX App Protect deployed on a Kubernetes Ingress Controller providing advanced security for the Kubernetes-deployed demo application, Arcadia Finance. These elements are being deployed and configured in an automated fashion using a Gitlab CI/CD pipeline. The visualization for NGINX App Protect is provided by NAP dashboards deployed in ELK. Note: For the purpose of supporting this lab, APM was configured as an OAuth Authorization Server supporting OpenID Connect. Its configuration, along with the implementation details of the third party banking application (AISP/PISP), acting as an OAuth Client, is beyond the scope of this article. In an OAuth Authorization Code flow, the PSU (End User) is initiating an API request through the Account or Payment Information Services Provider (AISP/PISP Application) which first redirects the end user to the Authorization Server. Strong Customer Authentication is being performed between the end user and Authorization Server which, if successful, will issue an authorization code and redirect the user back to theAISP/PISP Application. The AISP/PISP Application will exchange the authorization code for an ID Token and a JWT Access Token, the latter will be attached as a bearer token to the initial end-user API request which will then be forwarded to the API Gateway. The API Gateway will authenticate the signature of the JWT Access Token by downloading the JSON Web Key (JWK) from the Authorization Server and may apply further security controls by authorising the API call based on JWT claims and/or apply rate limits. Worth noting here is the security function of the API Gateway, which provides positive security by allowing only calls conforming to published APIs, in addition to authentication and authorization functions. The Web Application Firewall function, represented here by the NGINX App Protect deployed on the Kubernetes Ingress Controller (KIC), will add negative security protection, by checking the request against a database of attack signatures, and advanced API security, by validating the API request against the OpenAPI manifest and providing Bot detection capabilities. Configuration To configure the NGINX Controller API Management Module, first create an Application by sending a POST request to 'https://{{ my_controller }}/api/v1/services/environments/env_prod/apps' having the following body: { "metadata": { "name": "app_api", "displayName": "API Application Arcadia", "description": "", "tags": [] }, "desiredState": {} } Then create an Identity Provider, pointed at the Authorization Server's JWK endpoint, by sending a PUT request to 'https://{{ my_controller }}/api/v1/security/identity-providers/bank_idp' having the following body: { "metadata": { "name": "bank_idp", "tags": [] }, "desiredState": { "environmentRefs": [ { "ref": "/services/environments/env_prod" } ], "identityProvider": { "type": "JWT", "jwkFile": { "type": "REMOTE_FILE", "uri": "https://bank.f5lab/f5-oauth2/v1/jwks", "cacheExpire": "12h" } } } } Create an API definition by sending a PUT request to 'https://{{ my_controller }}/api/v1/services/api-definitions/arcadia-api-def/versions/v1' with the following body: { "metadata": { "name": "v1", "displayName": "arcadia-api-def" }, "desiredState": { "specs": { "REST": { "openapi": "3.0.0", "info": { "version": "v1", "title": "arcadia-api-def" }, "paths": {} } } } } Then import the OpenAPI definition by sending a PUT request to 'https://{{ my_controller }}/api/v1/services/api-definitions/arcadia-api-def/versions/v1/import' with the OpenAPI JSON as a request body. Publish the API definition by sending a PUT request to 'https://{{ my_controller }}/api/v1/services/environments/env_prod/apps/app_api/published-apis/prod-api', with the following body: { "metadata": { "name": "prod-api", "displayName": "prod-api", "tags": [] }, "desiredState": { "apiDefinitionVersionRef": { "ref": "/services/api-definitions/arcadia-api-def/versions/v1" }, "gatewayRefs": [ { "ref": "/services/environments/env_prod/gateways/gw_api" } ] } } Declare the necessary back-end components (in this example webapi-kic.nginx-udf.internal Kubernetes workload) by sending a PUT to 'https://{{ my_controller }}/api/v1/services/environments/env_prod/apps/app_api/components/cp_moneytransfer_api' with the following body: { "metadata": { "name": "cp_moneytransfer_api", "displayName": "cp_moneytransfer_api", "tags": [] }, "desiredState": { "ingress": { "uris": { "/api/rest/execute_money_transfer.php": { "php": { "get": { "description": "Send money to a friend", "parameters": [ { "in": "body", "name": "body", "required": true, "schema": { "type": "object" } } ], "responses": { "200": { "description": "200 response" } } }, "matchMethod": "EXACT" } } }, "gatewayRefs": [ { "ref": "/services/environments/env_prod/gateways/gw_api" } ] }, "backend": { "ntlmAuthentication": "DISABLED", "preserveHostHeader": "DISABLED", "workloadGroups": { "wl_mainapp_api": { "loadBalancingMethod": { "type": "ROUND_ROBIN" }, "uris": { "http://webapi-kic.nginx-udf.internal:30276": { "isBackup": false, "isDown": false, "isDrain": false } } } } }, "programmability": { "requestHeaderModifications": [ { "action": "DELETE", "applicableURIs": [], "headerName": "Host" }, { "action": "ADD", "applicableURIs": [], "headerName": "Host", "headerValue": "k8s.arcadia-finance.io" } ] }, "logging": { "errorLog": "DISABLED", "accessLog": { "state": "DISABLED" } }, "security": { "rateLimits": { "policy_1": { "rate": "5000r/m", "burstBeforeReject": 0, "statusCode": 429, "key": "$binary_remote_addr" } }, "conditionalAuthPolicies": { "policy_1": { "action": "ALLOW", "comparisonType": "CONTAINS", "comparisonValues": [ "Payment" ], "sourceType": "JWT_CLAIM", "sourceKey": "scope", "denyStatusCode": 403 } }, "identityProviderRefs": [ { "ref": "/security/identity-providers/bank_idp" } ], "jwtClientAuth": { "keyLocation": "BEARER" } }, "publishedApiRefs": [ { "ref": "/services/environments/env_prod/apps/app_api/published-apis/prod-api" } ] } } Note the 'security' block, specifying the JWT authentication, the Identity Provider from where to download the JWK, the authorization check applied on each request and the rate limit policy. The configuration used to deploy NGINX App Protect on the Kubernetes Ingress Controller can be consulted here. Summary In this article we showed how NGINX Controller API Management Module and NGINX App Protect can be deployed to protect API calls as part of the OAuth Authorization Code flow which is a basic flow used to control the access to many financial services APIs. Links UDF lab environment link.1.6KViews1like0CommentsHow to customise Azure AD OIDC user ID token for APM integration
Overview A Service Provider (SP) such as the F5 APM can integrate with Azure AD (AAD) as an Identity Provider (IDP) for federated authentication using OpenID Connect (OIDC). Through this process, a user visiting APM (e.g., https://myapps.acme.corp ) is immediately redirected to AAD for authentication, once authenticated, AAD returns a code to the APM via the user browser. The APM grabs that code, adds additional information, sends them together to AAD, and finally receives an ‘access_token’ and ‘id_token’. This article takes a special focus around what is included in ‘id_token’ that AAD returns, as it is used by APM, and broadly speaking by any relying party SP, for the purpose of session creation. ‘id_token’ (part of OIDC) contains user identity information and is highly customizable. The customization of ‘id_token’ is completely done within AAD. The concept is simple, but not until it is well understood in my experience; especially with the AAD having a bunch of configuration items in the mix, such as ‘Token configuration’, ‘API permissions’ and ‘Expose an API’. This article hopes to cut all the clutter and un-muddy the water so to speak, around this topic. OIDC As a refresher, the difference between oAuth and OIDC lies in that OIDC is an identity piece laying on top of oAuth. Specifically, with oAuth, ‘access_token’ alone is returned, whereas with OIDC, ‘id_token’ is returned in addition to ‘access_token’. Scope To tell AAD we are using OIDC, the APM needs to include a scope named ‘openid’ in its outbound request to the AAD. This is achieved via the following setting. Within AAD, your application must include ‘openid’, as shown below. By default, the ‘openid’ scope comes with a list of claims that will be included in ‘id_token’. However, for certain claims to be available, additional scopes are also required. For example, if you want to have ‘preferred_username’and ‘name’ claims included, ‘profile’ scope needs to be added as well, as is depicted in the following. AAD also lets you add optional claims via ‘Token configuration’ as shown below. If these optional claims need additional scopes, AAD will add those scopes in for you under ‘API permissions’. On the APM ‘OAuth Client’ configuration, make sure to add those scopes in as highlighted below. Once the APM matches scope with AAD, AAD will include all claims in ‘id_token’ it sends back to the APM. The APM is then able to consume those claims based on the use case (e.g., create a session using email) I am hoping that this short article sheds some light around your integration work around this space.1.5KViews2likes0CommentsF5 both as oauth provider and F5 resource server JWT introspect issue (JWK)
Dear all, We have a F5 Access policy that is configured for Oauth server and provides the access tokens and / or JWT. We have another Access policy configured as the F5 oauth resource server that acts as the API gateway (which is a pool behind the F5) Everything works when we perform external validation in the F5 resource server Access policy, which basically performs a scope check towards the F5 oauth server using introspect URL. It connects externally, hence the name external. So with this we only use the access token and are not using JWT. So the problem we have is when we change the validation to internal mode for the scope authorization object inside the Access profile. So with this is should validate the JWT payload (access token and claims included in payload). We request the JWT using parameter token_content_type=jwt and we do succesfully receive the JWT from the F5 oauth server. So from here all good, now we use this JWT encoded access token as the authentication bearer and perform a request to the F5 resource server to connect to the API server hosted behind the F5. No matter what we do with this "internal JWT validation method" we always receive Bearer error="invalid_token",error_description="None of the configured JWK keys match the received JWT token" and HTTP 401 not authorized in the response. We have actually succesfully and automatically retrieved the F5 oauth server keys so the F5 oauth resource server should be able to verify the JWT payload, however it fails. Perhaps someone here has some experience with using JWT and F5 as the Oauth server and F5 resource server to perform retroinspect with internal validation mode set in the Access profile for the Scope authorization check with the same problem related to JWKs validation?Solved1.5KViews0likes4Comments