Swagger UI sending "BearerToken" in header, need "Bearer" - oauth-2.0

I'm making a swagger-UI using swagger 2.0 generated in the integrated Apigee portal.
I'm trying to get the oauth2 client credentials(in swagger 2.0 called application) flow to work in the "try it out" part of the UI.
Note that the input from the user is the clientid and secret, and not the token.
When I try to authorize a get operation and send requests, I can see in the curl representation of the UI that the Authorization header is expressed "Authorization: BearerToken {token}". The token is replaced in the curl string as expected.
Apigee does not support the "BearerToken" prefix, only "Bearer".
Is there a way to force swaggerUI to use the prefix "Bearer" instead of "BearerToken"?
My securitydefinition:
securityDefinitions:
OAuth2:
type: oauth2
flow: application
tokenUrl: 'https://{org-environment}/token'
scopes:
read: Grants read access
My security definition in the path:
paths:
/resources:
get:
security:
- OAuth2: [read]

The name of the token is set from the response the oauth access token generation proxy.
I changed the token.type from "BearerToken" to "Bearer" and this solved my problem.

Related

Spring OAuth2 - JWT token working on server but not on localhost?

I am seeing that myapp is able to process the OAuth2 JWT token properly on the server, but it is giving token conversion error on localhost.
My Flow is as below -
On Server, the myapp is behind our custom api-gateway
Getting Access Token - Through postman, I hit api-gateway token endpoint which in turn calls the authserver token endpoint. And I get OAuth JWT Token as response.
So, to summarize, postman
request: --(creds)--> api-gateway --(samecreds) --> auth-server
response: jwt token <-- (same jwt)-- api-gateway <--(jwt)-- auth-server
Next, I hit myapp endpoint - Again through postman, I hit api-gateway endpoints, which in turn hits the corresponding myapp endpoints. And I get the required response. For this request, before hitting the api-gateway, I set the header Authorization: Bearer JWT from step1
As the myapp developer, i know that the api-gateway is re-sending the JWT token to myapp using the same header mechanism i.e Authorization: Bearer JWT from step1. From the logs, i see this is the same value that I provided in postman when hitting the api-gateway
So, postman request: --(jwt)--> api-gateway --(same jwt)--> myapp
and response is some data, which is trivial for this discussion.
The decoded JWT Payload is as below:
{
"app-userId": "c54a-4140-9fa0-0f39",
"user_name": "abc#xyz.com",
"scope": [
"all"
],
"exp": 1656929583,
"authorities": [
"app1_viewer",
"app1_modifier",
"app2_viewer",
"app2_blog_creator],
"client_id": "api-gw-client"
...
}
Plz note - "client_id": "api-gw-client" field in the above payload. So the auth-server is issuing the token to api-gateway client.
Now on mylocal dev env i.e myapp running on localhost - i am trying to achieve similar flow as on server.
On localhost, the myapp is NOT running behind api-gateway, but its hit directly
Getting Access Token - Through postman, I hit api-gateway (same server instance as in server flow above. i.e api-gateway/auth-server's are not running on localhost but are running on server) token endpoint which in turn calls the authserver token endpoint. And I get OAuth JWT Token as response.
So, postman request: --(creds)--> api-gateway --(samecreds) --> auth-server
response: jwt token <-- (same jwt)-- api-gateway <--(jwt)-- auth-server
Yes, this token can be used in Server Flow Step 2 and it works. And the decoded JWT token payload is same as I posted earlier i.e
{
"app-userId": "c54a-4140-9fa0-0f39",
"user_name": "abc#xyz.com",
"scope": [
"all"
],
"exp": 1656929583,
"authorities": [
"app1_viewer",
"app1_modifier",
"app2_viewer",
"app2_blog_creator],
"client_id": "api-gw-client"
...
}
Plz note again - "client_id": "api-gw-client" field in the above payload. So the auth-server is issuing the token to api-gateway client. I am not sure yet if this field is trivial or important.
Next, I hit myapp localhost endpoint - Again through postman, But I hit myapp endpoints directly (not through api-gateway running on localhost). And for this request, before hitting, I set the header Authorization: Bearer JWT from step1.
BUT THIS TIME I GET ERROR:
p.a.OAuth2AuthenticationProcessingFilter : Authentication request
failed: error="invalid_token", error_description="Cannot convert
access token to JSON"
I want to know what is causing this error. I don't think the client_id: api-gw-client is causing this. Anyhow, I created a signed jwt token with client_id: myapp and used it in request. But still I get same error.
The key I am using on localhost matches(corresponds) to the one that the auth-server is using to sign. I double checked. So its for sure not a key issue.
I need the localhost based setup working, so i can test my api's locally with out deploying to server(deploying to server is quite time consuming in my case). So this setup is quite important for me to meet my deadlines. Any answers/suggests are greatly appreciated.
The Spring OAuth2 Libraries used in my project are as below -
org.springframework.security:spring-security-oauth2-jose:5.4.2
org.springframework.cloud:spring-cloud-starter-oauth2:2.1.3.RELEASE
And the class which is giving error is: OAuth2AuthenticationProcessingFilter.java (API Doc)
Sorry, I won't answer your question (#Toerktumlare is right, your security configuration is missing) but will instead try to explain why I would not make the API gateway an OAuth2 client.
Simply put, the role of an API gateway is to be a black box for a system resources, which could make it seen as a resource-server, but it should, in my opinion, remain transparent to OAuth2 (and other authentication mechanisms). Keep things simple:
clients (UI) handle user login (when needed)
resource-servers control access to resources
gateway (if any) should remain as transparent as possible, just offering a single entry-point for all resources.
In your scneario:
how do you expect things to happen if you're asked to implement Multi Factor Authentication: in addition to login / password, require one of biometry, external app validation, Goolgle authenticator token or whatever? Do you really intend to implement all that in the gateway in addition to the authorization-server?
if it always get api-gw-client as client ID, how can your authorization-server achieve client based processing (like checking requested scopes are legit for a client, or adding client authorities to the access-tokens)?
what about multi-tenant scenarios (R1 and R2 resource-servers behind the gateway expect identities from different issuers, or C1 and C2 clients do not authenticate users against the same authorization-server)?
what if some clients and resource-servers use something else than OAuth2?
Also, your client(s) must know what media-type is accepted and produced at each API endpoint (XML, JSON, PDF, multipart, etc.) and set Content-type and Accept headers accordingly. Why would it be different for Authorization header?
In my opinion, if you want to save time and energy, use your API gateway to proxy your resource-servers only. Leave authorization-server(s) appart. Same for external APIs you do not maintain but your client(s) need, if any (Tweeter feed, Google API, etc.).
This is how I always configure my resource-servers:
Authorization header is missing or invalid (malformed, expired, wrong issuer, bad audience, etc.) => 401 (unauthorized) and not 302 (redirect to login)
in multi-tenant scenarios, why should resource-server bother figuring out which authorization-server to redirect to ?
What should be the meaning of a redirect for clients which are not running in a browser, like mobile apps?
Authorization header is valid but associated claims fail to pass access-control (bad authorities or not the expected subject for instance) => 403 (forbidden)
Clients should know how to aquire required access-token(s) and how to set Authorization header when it sends a request (this is what you curently do with Postman). It can even intercept 401 to trigger user authentication and then retry failed resource access. Serious OAuth2 client-side librairies (like angular-auth-oidc-client for Angular) provide with such features.
With such clients, gateway can act as facade for your resource-servers (and authorization-server or external APIs if you like, but why?), forwarding Authorization header and completely ignoring users login.

keycloak + Kong API Gateway

We are using keycloak to handle authentication (client/secret) in our API Gateway.
The Kong api service uses konnect-managed-plugin to refer to keycloak to authenicate client credentials and return a bearer token.
Future calls to other endpoints use oauth2-introspection to verify the bearer token via keycloak introspection
I almost have this working however, when I authenticate via Kong api gateway, it returns a bearer token, but this token fails introspection.
If I auth straight to keycloak, the bearer token works for introspection.
eg
Token from:
http://kongapigateway.domain/getOAuthToken
NOTE: We have not yet set up ssl on the kong api gateway
Returns:
{"access_token":"ey..ZiUQyw","expires_in":900,"refresh_expires_in":0,"token_type":"Bearer","not-before-policy":0,"scope":"email profile"}
Calling api endpoint in kong that uses introspection fails:
http://kongapigateway.domain/bookings
{
"error_description": "The access token is invalid or has expired",
"error": "invalid_token"
}
Direct call to keycloak introspection also fails:
https://keycloak.domain/auth/realms/{Realms}/protocol/openid-connect/token/introspect
{
"active": false
}
However if I get token direct from keycloak server:
https://keycloak.domain/auth/realms/{Realms}/protocol/openid-connect/token
{"access_token":"eyJhb...4lT8w","expires_in":900,"refresh_expires_in":0,"token_type":"Bearer","not-before-policy":0,"scope":"email profile"}
The token works for both endpoints:
http://kongapigateway.domain/bookings and https://keycloak.domain/auth/realms/{Realms}/protocol/openid-connect/token/introspect
So why doesn't the introspection work for the token returned in the first scenario
You can fix this by setting Keycloak's frontend URL to your public URL. For details please refer to my answer to another but similar question.

Rest Assured Framework - Handle Bearer Token, X Api key for Apigee proxy URL

I am trying to create Test Automation framework for Apipgee Proxy URLs.
I am using Rest Assured Framework for Apigee proxy URLs with generating Bearer token on the fly ,Xapi Keyand use Apigee proxy URL. For now token is generated manually using CURL command . I can test well in postman.
// accessToken,apiKey below is defined as string
// inputrequest.getInputStream() reads JSON needed for body
response= RestAssured
.given()
.headers("Authorization","Bearer "+ accessToken)
.headers("apiKey", apiKeyVar)
.contentType("application/json")
.body(inputrequest.getInputStream()).When()
.post(apigeeProxyURL).then().statusCode(200).extract().response();
I am getting 401 (Unauthorized error) instead of 200. My query here to summarize--
Does RestAssured Framework Supports Apigee Proxy URL .
if same x-api Key and Bearer token works in postman for same end point, why its throwing an error
I read some blogs with variation on how to pass x-api Key and Bearer Token
Please revert back and share directions on how to approach for REST API Automation for Apigee Proxy URLs
Thanks and Regards,
Aditya Mandlekar
Check if you are passing the apikey at the correct place . By default it should pass in the query param. Check your verifyapikey policy which you must have attached to your proxy.

Why send "Bearer" text in Header

It has always been haunting me but i can't find the answer.
When sending bearer token, why does one send the "Bearer" string also usually (i.e: Bearer abcd1234), isnt it enough with just the token only?
The Authorization header can be used with different authorize schemes like Basic or Digest. The Bearer scheme indicates that you are using a bearer token.
The HTTP authorization scheme can be extended with custom schemes.
See https://www.rfc-editor.org/rfc/rfc2617 for more information

microsoft_graph oAuth refresh error

I allow users to authorize their Microsoft accounts using oAuth and the Microsoft Graph API. I am using this omniauth strategy to facilitate the authorization. In the OmniAuth strategy, it includes the resource for both authorize_params and token_params "https://graph.microsoft.com". This allows me to authenticate just fine but when I go to refresh the auth, I get this error returned:
{"error"=>"unauthorized_client", "error_description"=>"AADSTS70001: Resource 'https://graph.microsoft.com/' is not supported as resource.\r\n"}
Along with a trace_id and some other things that I will post if needed.
The endpoint I am hitting to refresh is POST https://login.microsoftonline.com/common/oauth2/v2.0/token with the client_id, refresh_token and grant_type: "refresh_token" params.
Refreshing this oAuth token was working fine as recently as last week. Did something change with the Microsoft Graph API or something?
You may want to take a look at Refreshing a Token.
It sounds like you were partially there, you were just missing some additional parameters:
grant_type - Set as refresh_token
refresh_token - The refresh token value you received from the Provider
client_id - This is your Application ID from above
client_secret - This is the Password we generated before
scope - This should match the same set of scopes you first requested
redirect_uri - This is the redirect URI defined in your application registration
These are formatted application/x-www-form-urlencoded in you POST to https://login.microsoftonline.com/common/oauth2/v2.0/token
POST URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
POST HEADER: Content-Type: application/x-www-form-urlencoded
POST BODY: grant_type=refresh_token&refresh_token=[REFRESH TOKEN]
&client_id=[APPLICATION ID]&client_secret=[PASSWORD]
&scope=[SCOPE]&redirect_uri=[REDIRECT URI]
Turns out it was as simple as I was authing to v1.0 but attempting to reauth to v2.0. Not sure why this worked up until now but ensuring they are hitting the same version of the API has solved the issue.

Resources