I currently secure my API (running on k8s) with an oauth2-proxy which then redirects requests to the API.
As the scope of content (on API-level) should vary based on subgroups, these groups should be authorized only for their entitled scope. The Access Token provides the required subgroups affiliations but I cannot bridge the gap between the proxy handling the authentication and the API doing the authorization. I also just want to use a single API and oauth2 infrastructure.
Is it possible to pass the Access Token to the downstream API? What are best practices for this pattern?
Can someone point me in the right direction?
Cheers
Yes, that's possible: See the --pass-access-token and --set-xauthrequest options in oauth2-proxy.
E.g., I use this in oauth2-proxy.cfg
# Get JWT in x-auth-request-access-token
pass_access_token = true
set_xauthrequest = true
combined with this in the nginx ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-response-headers: x-auth-request-access-token # This holds the JWT (without 'Bearer ')
nginx.ingress.kubernetes.io/auth-signin: http://dev.k8s.ese-ia/oauth2-proxy/start # external URL!
nginx.ingress.kubernetes.io/auth-url: http://oauth2-proxy.ese-ia.svc.cluster.local/oauth2-proxy/auth # internal service URL – must be fqdn to be reachable from the ingress!
Note that the header name is not Authorization and that there is no Bearer prefix in the value. So the services using it might have to be changed. E.g, if you use Spring Boot, you will have to set a custom BearerTokenResolver.
(Bonus: If you use an AWS ELB with OIDC authentication instead of oauth2-proxy and an nginx ingress, the system is basically the same. Only the header name is different.)
Related
I have an emissary ingress gateway and I want to authenticate requests with my keycloak server. I see that the integration is available with Edge Stask but, there is an alternative solution ready to use to solve the auth problem? thanks.
Emissary ingress has a feature called authservice. This allows you to create the authservice kind and point it to a backend service to handle authentication.
When using keycloak you can use openIDConnect from your authservice backend to authenticate users to keycloak.
https://www.getambassador.io/docs/emissary/latest/topics/running/services/auth-service/
I have an apollo/graphql server sitting behind a GCP API gateway. Google says it requires an OpenAPI spec to secure endpoints:
https://cloud.google.com/api-gateway/docs/get-started-cloud-run#creating_an_api_config
But how exactly would this look for securing a single graphql endpoint? Also, as a side question, is a new API Gateway needed to be created for each Cloud Run/App Engine service?
Thanks in advance.
Here's a repo that demonstrates what you want to achieve. It's a GCP API Gateway fronting a GraphQL API on Cloud Run, secured with Identity-Aware Proxy. Here's the API config from the link:
api-spec.yaml
swagger: '2.0'
info:
title: gcp-demo-api
description: Sample GraphQL API on API Gateway with a Cloud Run backend
version: 1.0.0
schemes:
- https
produces:
- application/json
paths:
/:
post:
summary: GraphQL endpoint
operationId: gql
x-google-backend:
address: https://PROJECT_AND_RANDOM_STRING.a.run.app/graphql # App URL/endpoint
jwt_audience: LONG_RANDOM_STRING.apps.googleusercontent.com # IAP client ID
responses:
'200':
description: A successful response
schema:
type: object
To answer your side question, it is important to understand what an API Gateway does. An API Gateway is what stands between your user requests and your collection of backend services so all API requests goes through it.
Therefore, you don't need to create a new API gateway for each service. It is possible in API Gateway to serve multiple services such as Cloud Run, App Engine, Cloud Functions, etc. by specifying the backend address on each endpoint. Here's a link that further explains the concept.
I'm using KONG API Gateway, and I want to implement JWT authentication as separate microservice (not using KONG plugin), now I can easily register this service with KONG, and so users can register and login. Assume an authenticated user had sent a request with a token attached in the header, how to make KONG forwards the request to the authentication service first, then if it is valid the request is forwarded to the requested service?
Yes you can (But I have not used them) there is as far as I know two options:
https://docs.konghq.com/hub/kong-inc/openid-connect/ Enterprise
https://github.com/aunkenlabs/kong-external-auth Free
In a microservice architecture, an API gateway lays in front of the API. The purpose of this is e.g. changing some request / response parameters, for single entry point or checking authentication etc. Now I would like to protect my API using OAuth2 flows to obtain an access token. The problem is to decide who is the actual OAuth client, I will demonstrate it by using a SPA example:
a) Is it the SPA that started the oauthorize request (to the api gateway) by using the implicit grant. Then, the Api gateway would simply route the request through to the OAuth authorization server, acting as a single entry point, with the /authorize stuff from the implicit flow
b) Is it the API Gateway itself, meaning the SPA sends the username and password of the enduser to the api gateway (of course, here the SPA needs to be trusted with the end users credentials), which then acts on its own as an oauth client using the resource owner password grant
c) dismiss the api gateway at all and create the oauth authorization server "parallel" to the api gateway, meaning you would loose the single entry point etc.
The following picture demonstrate a very abstract architecture, and the question is about the numer "[2]", if this request is initiated by the SPA and passed through by the api gateway, or if the api gateway is intercepting the request and acting on its own as an oauth client?
OAuth with API Gateway
My guess is to always use the best fitting grant type for a specific client, regardless of an API gateway being in between or not. This would mean, that when it comes to OAuth, the API Gateway would simply pass the client authorization request through, whatever grant type it used. Therefore, [2] in the picture would come from the client, and not from the API Gateway acting as the OAuth client. Is this correct? As mentioned, this really gets tricky when it comes to first party apps as you probably could use the password credentials grant, which has huge drawbacks,e.g. no refreshing possible for SPAs.
Please bear in mind that this is a purely opinion based answer, because your question is pretty vague.
I don't like the idea about using the API Gateway as the point which authenticates requests. I think that this defeats the Single Responsibility Principle. The gateways purpose usually is to expose your backend to external clients, perhaps change the contract for some specific clients, etc. But it shouldn't also authenticate calls. Besides it would have to do so based on the data passed to it, which you would have to gather somewhere else anyway.
Another thing which is I think undesirable, is that you're considering using the resource owner password grant for your SPA. This is not the correct use case for this grant flow. You could look into this article, which explains it much better than I could: https://www.scottbrady91.com/OAuth/Why-the-Resource-Owner-Password-Credentials-Grant-Type-is-not-Authentication-nor-Suitable-for-Modern-Applications
I would suggest you use the Implicit grant type and use the api gateway to only route calls to the backend, don't authenticate the calls on that layer.
If you're using a spring cloud api gateway (essentially a zuul proxy), you will have to add proper configuration so that it forwards all security headers and redirects. This example works for me:
server:
use-forward-headers: true
zuul:
addHostHeader: true
routes:
<your oauth server route>:
url: <your oauth server url>
path: <if youve got any prefix>
sensitiveHeaders:
stripPrefix: false
It doesn't matter, what Krzysztof Chris Mejka in previous answer like or dislike. Take a look at BCP - https://datatracker.ietf.org/doc/html/draft-ietf-oauth-browser-based-apps#section-6
Latest recommendation from oauth working group at IETF is to use a kind of Api gateway/reverse proxy, another words - you need to keep tokens out of js entirely.
I have successfully set up multiple API Gateways on AWS and they work perfectly with client API Keys.
Is it possible to make a specific endpoint in an API publicly available, but all other endpoints protected with the client API key required?
Simply set the apiKeyRequired field to false on whichever Methods you want to open to the public.
This is in the Method Request page in the console. Here is an example using the AWS CLI:
aws apigateway update-method --rest-api-id 1234123412 --resource-id a1b2c3 --http-method GET --patch-operations op="replace",path="/apiKeyRequired",value="false"
Please note that if you remove the requirement for an API Key, any rate limit or quota you have set up on a Usage Plan will not be applied.
You can use AWS CloudFront to forward the request to API Gateway for the public endpoint and define the Client API Key in CloudFront headers forwarded to the Origin.
Note: When including API Gateway as a origin to CloudFront you need to do the following.
Whitelist header (Except Host Header)
Make HTTPS only
Make TTL values 0