Kuadrant / authorino

K8s-native AuthN/AuthZ service to protect your APIs.
Apache License 2.0
195 stars 30 forks source link

Allow for dynamic unauthenticated/unauthorized responses #491

Open OperationalDev opened 23 hours ago

OperationalDev commented 23 hours ago

Current Issue

We have some services behind an authconfig that are used by both systems and users from a browser. When a user tries to access the services from their browser and is unauthenticated, we return a 302, similar to the example here https://github.com/Kuadrant/authorino/blob/main/docs/user-guides/deny-with-redirect-to-login.md

However when a system makes a call to the service, we don't want to give them back a 302, we want to be able to give them back a 401 instead.

At the moment we have this working by using response.unauthenticated to always return a 401 and then using response.unauthorized to return a 302 and making user requests skip response.unauthenticated which works well, but it makes it difficult to add authorization as well for other use cases.

Possible solutions

Having multiple response.unauthenticated/unauthenticated responses (similar to how we can have multiple authentication types) and then using priority and when to determine which ones are invoked.

apiVersion: authorino.kuadrant.io/v1beta2
kind: AuthConfig
metadata:
  name: matrix-quotes-protection
spec:
  hosts:
  - matrix-quotes.127.0.0.1.nip.io
  authentication:
    "browser-users":
      apiKey:
        selector:
          matchLabels:
            group: users
      credentials:
        cookie:
          name: TOKEN
    "http-basic-auth":
      apiKey:
        selector:
          matchLabels:
            group: users
      credentials:
        authorizationHeader:
          prefix: Basic
  response:
    unauthenticated:
    - name: unauthenticated-browser
      code: 302
      priority: 0
      headers:
        "Location":
          selector: "http://matrix-quotes.127.0.0.1.nip.io:8000/login.html?redirect_to={request.path}"
      when:
      - selector: context.request.http.headers.user-agent
        operator: matches
        value: "Mozilla"
    - name: unauthenticated-system
      code: 401
      priority: 1
guicassolato commented 21 hours ago

Hi @OperationalDev. Thanks for suggesting this feature. It sounds an interesting use case to cover.

I imagine that, in case multiple custom responses match (same priority, both blocks of when conditions evaluating to true), then whichever config happens to evaluate first wins, similarly to how authentication and authorization phases work already?

OperationalDev commented 12 hours ago

TBH I hadn't thought about that use case as I tend to always use priority, but to keep things consistent, I think it would make sense to make it behave the same way.