BlogDocumentation
Products
Identity ProtectionIdentity ManagementBlogDocumentation
Vincenzo Iozzo
Vincenzo Iozzo
18 Sep, 2023
Introduction WebAuthn and phishing The internal app: YouTrack Deploying Gate Customizing the login page Creating complex authorization policies Seeing it in action Conclusion
Tutorial
No-code anti-phishing protection of internal apps with Passkeys

Phishing is one of the most common causes of data breaches. According to Verizon's DBIR report, over 50% of incidents start with phishing or stolen credentials. WebAuthn/Passkeys are an effective way to stop phishing and credential stealing attempts on their tracks.

In this article, we’ll show how you can use Gate to enforce Passkeys authentication for users without modifying the application code.

No-code anti-phishing protection of internal apps with Passkeys

Introduction

Phishing is among the most common causes of data breaches. Attackers often trick users into inputing their credentials into websites that look legitimate to the human-eye but are actually setup by the attacker to steal credentials.

While MFA is an effective tool to reduce this kind of attacks, it is unfortunately insufficient. Multiple campaigns in the past have shown how attackers can get around MFA through various techniques.

WebAuthn/Passkeys provide strong protection against phishing attacks. In fact, all compliant browsers enforce a number of security checks that render phishing unfeasible in the majority of scenarioes.

Enforcing access to apps through Passkeys is not always possible as the company might not have access to the source code or might not have the resources to dedicate to the project. Gate is an effective way to easily enforce complex authentication and authorization policies out-of-the-box on web applications without any code changes.

Read on to see an example on how to add fine-grained access control and Passkeys auth to an arbitrary application in 10 minutes or less.

WebAuthn and phishing

WebAuthn/Passkeys are public-private keypairs where only the public key is transmitted to the server, making credential stealing unfeasible unless an attacker compromises a user machine.

Further, the WebAuthn spec and implementations in the browsers have been designed to be phishing-resistant and several checks are in place for an authentication ceremony to happen.

First of all, WebAuthn doesn’t work without TLS. Furthermore, browsers enforce origin checks and most will prevent access to the platform authenticator unless the window is in focus or, in the case of Safari, the user triggers an action.

In other words, an attacker trying to compromise user credentials will need to either find a cross-site scripting (XSS) bug in the target website or a vulnerability in the browser, both of which are very high barriers to overcome. This is the only way in which they can bypass the WebAuthn checks.

In either scenario, a successful attack still won’t give the attacker access to the private key itself, but only to a session token/cookie which will expire once the browsing session is over.

Most importantly, due to the origin checks, most of the recent attacks involving domain squatting and phishing would fall flat because the reverse proxy wouldn’t be able to initiate the WebAuthn authentication process.

In comparison to all other authentication methods — where an attacker only has to register a seemingly related domain and have a similar looking webpage to fool the victim through phishing — it is clear that WebAuthn is a vastly superior authentication method.

The internal app: YouTrack

For this example we are going to assume that we have a self-hosted deployment of YouTrack, the popular issue tracker software. For simplicity, we’ll use docker compose for the deployment but Gate supports several deployment topologies.

version: '3.3'

services:
  youtrack:
    image: jetbrains/youtrack@sha256:<hash>
    container_name: 'youtrack'
    volumes:
      - /mnt/disks/youtrack-data/youtrack/data:/opt/youtrack/data
      - /mnt/disks/youtrack-data/youtrack/conf:/opt/youtrack/conf
      - /mnt/disks/youtrack-data/youtrack/logs:/opt/youtrack/logs
      - /mnt/disks/youtrack-data/youtrack/backups:/opt/youtrack/backups
    expose:
      - '8080'

Deploying Gate

We are going to deploy Gate in front of the application such that Gate can intercept unauthenticated requests and prompt the user to login. Visually, it looks as follows:

Configuration

What the Authentication Proxy plugin does is to intercept HTTP requests and if no valid authentication token is found, Gate injects a login page in front of the application. The user logs in with one of the allowed login methods and is then redirected to the original app (in this case YouTrack).

Once the user has authenticated the first time, future requests are passed to YouTrack transparently.

Here’s what the docker compose looks like:

version: '3.3'

services:
  youtrack:
    image: jetbrains/youtrack@<hash>
    container_name: 'youtrack'
    volumes:
      - /mnt/disks/youtrack-data/youtrack/data:/opt/youtrack/data
      - /mnt/disks/youtrack-data/youtrack/conf:/opt/youtrack/conf
      - /mnt/disks/youtrack-data/youtrack/logs:/opt/youtrack/logs
      - /mnt/disks/youtrack-data/youtrack/backups:/opt/youtrack/backups
    expose:
      - '8080'

  gate:
    container_name: gate
    image: slashid/gate:latest
    command: ['-env']
    hostname: gate
    restart: unless-stopped
    environment:
      - GATE_PORT=80
      - GATE_DEFAULT_TARGET=http://youtrack:8080
      - GATE_LOG_FORMAT=text
      - GATE_LOG_LEVEL=info
      - GATE_HEADERS_FORWARDED_SET_OUTBOUND_X_FORWARDED=true
      - GATE_HEADERS_FORWARDED_PRESERVE_INBOUND_X_FORWARDED=true
      - GATE_PLUGINS_1_TYPE=authentication-proxy
      - GATE_PLUGINS_1_ENABLED=true
      - GATE_PLUGINS_1_PARAMETERS_LOGIN_PAGE_HEADING=Welcome to YouTrack
      - GATE_PLUGINS_1_PARAMETERS_STORE_LAST_HANDLE=true
    env_file:
      - .secret.env
    ports:
      - '80:80'
    depends_on:
      - youtrack

Customizing the login page

The authentication proxy plugin supports a number of customization, as shown in the documentation.

In particular, it is possible to specify the valid authentication methods supported:

login_page_factors:
  - method: 'webauthn'
    options:
      <Factor option>: '<Factor option value>'
  - method: 'oidc'
    options:
      <Another factor option>: '<Another factor option value>'

Creating complex authorization policies

The authentication proxy plugin also allows to out-of-the-box restrict access to users belonging to specific groups. For example, we could restrict access to users belonging to the developers group.

required_groups: ['developers']

But sometimes it might be necessary to enforce more complex policies. For instance, we might want to restrict access to users that belong to certain google groups. To do so, we can combine the OPA plugin with the Authentication Proxy plugin. Let’s see how:

...
    - id: authz_admin_oidc
      type: opa
      enabled: true
      parameters:
        <<: *slashid_config
        policy_decision_path: /authz/allow
        policy: |
          package authz

          import future.keywords.if
          default allow := false

          allow if claims.oidc_tokens[0].oidc_groups[_] == "[email protected]"

          parseCookies(cookies) = cookie {
              parsed = split(cookies, ";")

              cookie = { k: v |
              	  raw = parsed[_]

                  pair = split(raw, "=")
                  k = trim(pair[0], " ")
                  v = trim(substring(raw, count(sprintf("%s=", [pair[0]])), count(raw)), " ")
              }
          }

          cookies := c if {
              v := input.request.http.headers.Cookie[0]
              c := parseCookies(v)
          }

          claims := payload if {
              [_, payload, _] := io.jwt.decode(bearer_token)
          }

          bearer_token := t if {
              t := cookies["SID-AuthnProxy-Token"]
          }

    - id: auth_proxy
      type: authentication-proxy
      enabled: true
      parameters:
        <<: *slashid_config
        login_page_heading: "Hello!"
        jwt_expected_issuer: https://api.slashid.com
        jwks_url: https://api.slashid.com/.well-known/jwks.json

        login_page_factors:
          - method: "oidc"
            options:
              client_id: "<google client id>"
              provider: "google"
  urls:
    - pattern: "*"
      target: http://youtrack:8000
      plugins:
        auth_proxy:
          enabled: true
        authz_admin_oidc:
          enabled: true
...

Let’s break it down, the authentication proxy configuration specifies oidc as the only valid authentication method. You can read more here on how to configure SlashID to retrieve Google groups as part of the authentication process with OIDC.

Note: you could do the same with AzureAD. Read here to learn more.

The authz_admin_oidc instance of the OPA plugin enforces the check on the presence of Google groups as follows:

  1. Parse the cookies in the headers
  2. Extract the bearer token from the SID-AuthnProxy-Token header
  3. Check if the oidc_groups array in the token contains the [email protected] group

We could, of course, further restrict the policy to, for instance, specific IP addresses or user agents. The Gate OPA plugin provides a rich input object to the policy with significant information on the incoming request.

Seeing it in action


Conclusion

In this post, we’ve shown how we can easily add Passkeys and fine-grained authorization policies to an arbitrary web application in less than 10 minutes without modifying its source code.

We’d love to hear any feedback you may have! Try out Gate with a free account. If you’d like to use the PII detection plugin, please contact us at [email protected].

Related articles

Rate Limiting for Large-scale, Distributed Applications and APIs Using GCRA

Tutorial

/ 16 Oct, 2023

Rate Limiting for Large-scale, Distributed Applications and APIs Using GCRA

Rate limiting is a key defense against bots and threats for APIs and backends. Traditional IP-based rate limiting techniques are insufficient today because they can be easily bypassed.

In this article, we discuss the state of the art when it comes to rate limiting and how we have implemented a modern, distributed, identity-based rate limiting plugin for Gate.

Paulo Costa, Vincenzo Iozzo
Paulo Costa, Vincenzo Iozzo
Paulo Costa, Vincenzo Iozzo
Context-aware authentication: fight identity fraud and qualify your users

Tutorial

/ 10 Oct, 2023

Context-aware authentication: fight identity fraud and qualify your users

Knowing your users is becoming increasingly important. Whether you're a B2B PLG business trying to convert leads or a fintech business fending off attacks, it's essential to have more context about who is accessing your platform and to customize your behavior accordingly.

In this article, we show how you can leverage SlashID's webhooks to enrich the authentication context, customize the user journey, block malicious users.

Vincenzo Iozzo
Vincenzo Iozzo
Firewalling OpenAI APIs: Data loss prevention and identity access control

Tutorial

/ 14 Sep, 2023

Firewalling OpenAI APIs: Data loss prevention and identity access control

Large Language Models (LLMs) have taken the world by storm, and they are now used for many tasks by consumers and enterprises alike. However, the risk of accidentally disclosing sensitive data to the models is very high as the recent Samsung case shown.

In this article, we’ll show how you can use Gate to detect sensitive data in requests sent to the OpenAI APIs, as well as enforcing access control so that only users with certain roles can access the APIs.

Vincenzo Iozzo
Vincenzo Iozzo

Ready to start a top-tier security upgrade?

Terms · Privacy · System Status
© 2025 SlashID® Inc. All Rights Reserved.

Products

Identity Protection Identity Management

Resources

Blog Get in touch

We use cookies to improve your experience. Read our cookie policy.