Skip to content

Access Control

Game Warden authenticates users via Keycloak. However, we do not control nor do we provision users of your application. You can parse the provided JWT to identify users with unique fields and configure your application logic to associate them with necessary permissions and or groups needed to interact within your application.

FAQ: What is Keycloak?

Keycloak is the Identity and Access Management (IAM) solution that we employ to authorize users to reach the Game Warden App and Game Warden-hosted applications. It integrates with the Platform One Single Sign-on (P1 SSO) such that you only need one set of credentials for secure access.

FAQ: Do I need to set up a Keycloak account?

By performing the steps of the New User Account article, you automatically establish your own Keycloak account.

Application Access

By default, anyone who has your application’s endpoint - be it in the Development (DEV), Staging (STG), or Production (PRD) environments - will have access. Some caveats to keep in mind:

  • All users (developers and end-users) must establish a P1 SSO account to access Game Warden-hosted applications - and -
  • If an application is hosted at Impact Level (IL) 4 or higher, the end user must possess a Government Access Card with the appropriate permissions* to access that impact level.
    • These permissions are dictated by the end-user’s DoD command.
  • Users with .gov or .mil email addresses automatically have access to IL2, IL4, and IL5 environments when they use their Government Access Cards

JWT Authorization

FAQ: What is a JSON Web Token?

JSON Web Token (JWT) is a compact URL-safe means of representing claims to be transferred between two parties. For more information, see here.

A JWT has three parts, each comprising specific data:

  • Header – The header includes the token type, JWT, for example. It also includes the algorithm in use, such as “alg”: “HS256” (which works in conjunction with the Signature to verify users and is used to encode/decode data), and a token expiration date.

  • Payload – Includes user information and any designated groups/roles. For example, the payload will include the sub or subject, such as the user ID. It also will include the username.

  • Signature – Reviews header and payload data before it is returned to the server to ensure the client has not altered this data. Verifies the JWT sender (user) and, if valid, grants application access.

JWT authorization exists for each user request. Application teams might leverage this tool solely for authentication. They also might manage authorization internally relative to application code, if they require role or group-based authentication.

The Process

When integrating your applications with Game Warden, two primary actions occur:

  • Authentication (AuthN)
    • Keycloak authenticates user requests.
  • Authorization (AuthZ)
    • Keycloak determines the level of access a user should receive.
    • If a user registers with a DoD-supported Public Key Infrastructure (PKI) method (using a Government Access Card), our Keycloak SSO automatically assigns the appropriate Impact Level groups and roles from Platform One.

After the Authservice validates a request, it sets the Authorization: Bearer header (which contains JWT authentication) in the request that it passes into the application code. This data is in JWT format, can be parsed with any JWT library, and contains the user's Keycloak profile.

Due to this process any pre-existing Authorization header will be stripped and replaced with the aforementioned JWT (JSON Web Token).

Developers can identify data within encoded and decoded JWTs by viewing each of its three parts: Header, Payload, and Signature.

Sample Decoded JWT with Payload Data decoded

Sample Encoded JWT - An encoded JWT displays the Header, Payload, and Signature. A period separates each. encoded

See below for a visual representation of our authservice flow:

Best Practices

On initial login: The frontend app is unaware of who you are, but after login, you will have a cookie that Authservice uses to get your keycloak session information.

Once the frontend is loaded on the client’s machine, the client needs to make a request to the backend, where the API endpoint is looking for the authorization header in the request which contains the JWT in Authorization: Bearer format. The TOKEN is a JWT that can be decoded with a multitude of libraries without any extra information, though more info is needed to verify the token (optional, the cluster injects it, so it will be valid).

Note

In the usual OIDC process, your customer app would load: if you're not logged in, it would redirect you to keycloak to get a session, then keycloak would redirect you back (callback) once logged in, and your app would use that session and pass around an authorization header manually. That flow gets completed before the end user receives a single byte of your (customers) app, so you do not need to take on any of that unneccessary manual work.

In the Game Warden process, Once you hit the cluster itself, again, before your customer app loads, it's going to redirect you to keycloak automatically, if not already logged in.

  1. Once you log in, keycloak redirects you back to the cluster, where authservice running in the cluster is going to grab the keycloak session from the cookie, and inject the authorization header to subsequent requests from the client.
  2. Once the login flow is completed, your customer app needs to make another request to something inside the cluster (i.e., your backend most likely) where you can read the authorization header from the request. Wherever you receive the request, you can check if there is an auth header; if there is one: break it up to get the JWT, decode it, and then determine the user.
  3. At this point, for more control of end users, you can add your own login/user database to query, return the user with the sub if it exists, and if not, create one and return it.
    4.You then just have to code functionality into your app for user control, so you can manage if UserX, for example, should be an Admin, or belongs to a certain role within your app.
  4. For a default admin functionality within your app, you could potentially use the email domain (not entirely safe), or better, the groups field. Within groups, all of Game Warden’s customer developers will have /Customers/CompanyName/developers that 2F does control, which is the same group that gives you access to your App in ArgoCD.

Note

The reason to use sub inside the JWT is because that is the keycloak subject ID, which will always be unique to that user account, even if you change email/names/affiliations, etc. It is in GUID format, so it is a pretty long value.

Example

You can store users’ roles/groups in the application database and use the authenticated ID of users in the JWT to compare to those groups using the application code.

Note

You must manage your application user roles and permissions.

You could use email domain as a simple access control, but make sure the email is verified. This method is not recommended though. For example:

  emailVerified = user["email_verified"]
  emailDomain = user["email"].split("@")[1]

  if emailDomain == "mycompany.com" && emailVerified == true:
    user["isAdmin"] = true

Instead, you could use groups as a simple access control. The JWT includes groups assigned in keycloak and they are set by the platform at a basic level. You can verify the correct group is present and flag the user as an admin, for example:

  groups = decodedToken["groups"]

  if groups.contains("/Customers/mycompany/developers"):
    user["isAdmin"] = true

Note

These examples are non-functional, but meant to give an understanding of how you as a Game Warden customer might structure your app auth.

Frontend

# This is a function that runs on initial load of your frontend.
func getUser:
  user = get("backendUrl/api/whoami")

  if user == null:
    error.log("something went wrong fetching user info")
    return null
  else:
    return user


# The function that renders your frontend
func rendersFrontend:
  # Call the backend to get user info
  user = getUser()

  # Until a user is returned, present a loading page
  if user != null:
    return <yourFrontend>
  else:
    return <loadingPage>

Backend

# Attached to "/api/whoami" endpoint, accepts GET requests, returns simple user info
func whoami(request):

  # Grab authorization header, it'll look like: "Bearer <JWT>"
  authHeader = request.headers["authorization"]

  # Isolate the JWT from the header, for example by splitting the string on space and picking the 2nd element of the resulting array, ["Bearer", "<JWT>"]
  token = authHeader.split(" ")[1]

  # Decode JWT to expose user info, libraries available from https://jwt.io/libraries
  decodedToken = jwt.decode(token)

  # To verify the jwt (optional), you can find the public key from https://login.afwerx.dso.mil/auth/realms/gamewarden/protocol/openid-connect/certs

  # Extract userinfo from decoded JWT, an example is found in the help center Access Control article
  user["id"] = decodedToken["sub"]
  user["firstName"] = decodedToken["given_name"]
  user["lastName"] = decodedToken["family_name"]
  user["email"] = decodedToken["email"]
  user["emailVerified"] = decodedToken["email_verified"]
  user["groups"] = decodedToken["groups"]

  return user

You could use email domain as a simple access control, but make sure the email is verified. This method is not recommended though. For example:

  emailVerified = user["email_verified"]
  emailDomain = user["email"].split("@")[1]

  if emailDomain == "mycompany.com" && emailVerified == true:
    user["isAdmin"] = true

Instead, you could use groups as a simple access control. The JWT includes groups assigned in keycloak and they are set by the platform at a basic level. You can verify the correct group is present and flag the user as an admin, for example:

  groups = decodedToken["groups"]

  if groups.contains("/Customers/mycompany/developers"):
    user["isAdmin"] = true

Note

For more fine-grained control of users, the simplest option would be to use the information from the JWT to derive an ID and populate some user fields, and store the user in an external database. The Keycloak subjectId (sub in the JWT) is a unique field. This method allows for your internal application to manage users via application functionality as the platform does not provide fine-grained user management.

Authorization Policies

Game Warden uses Istio in concert with Keycloak to employ authorization policies. Customer configured, customized Authorization Policies can be used to limit access to endpoints using Gamewarden’s keycloak groups, giving you options for granular access control.

  • For example, an authorization policy could limit access to your developers in a DEV environment or you could permit only Airforce users to access your endpoint.

After you draft your policy, provide it to your Customer Ops representative and we will apply it to your cluster.

Example Policy
# This policy ensures that Identities without this string  
# "/Customers/<customer_name>/<some group>" in their JWTs 
# group claim are not allowed to reach pods and services 
# labeled with "app.kubernetes.io/name": foo  

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "pgadmin-allow-mmt-developer-group"
  namespace: "mmt"
spec:
  selector:
    matchLabels:
      "app.kubernetes.io/name": foo
  action: DENY
  rules:
  - to:
    - operation:
        hosts: [foo.il2.afwerx.dso.mil"]
    when:
    - key: request.auth.claims[groups]
      notValues: ["/Customers/<customer_name>/<some group>"]


# Auth Pols are granular and flexible in nature instead 
# of blocking for a whole host you could just block for a path 
# instead by changing the rule object to some like this
- to:
  - operation:
      paths: ["/admin"]
  when:
  - key: request.auth.claims[groups]
    notValues: ["/Customers/<customer_name>/admins"]

# This would have the effect of only allowing users with the admin group 
# in the claim from being able to hit the admin endpoints within the application

Reach out to your Customer Operations representative or submit a Support Ticket for any questions you may have.

Account Time-out

Users who are not actively accessing Game Warden resources (and authenticating via Keycloak) will be deactivated after 30 days of inactivity.

Deactivated users will be sent an email notification:

Clicking the Login button will take the user to a page asking for their username. For users logging in with a DoD PKI, their account is restored.

For users without a DoD PKI, after entering their username, a verification email is sent. After the user verifies via email, their account is restored.

Note

If you end user missed the email, they can click on this link to start the account re-enablement process.

FAQ

How does a customer of Game Warden add groups or roles?

This is controlled by your application as described above in conjunction with the parsing of the JWT created upon user login.

How and when does a web application session timeout?

The Keycloak configuration for user session timeouts is set to 4 hours.

How does multi-tenant applications work on Game Warden?

This is an application control and is not configured by Game Warden employees. To take advantage of user segriagation the recommendation is to implement user controls within your application.

Can I use a custom authorization header?

Yes, you can configure a custom authorization header to be used in your application however using the default Authorization will be interpreted by the system and stripped as described above.

Feedback

Was this article helpful? Want to see something more?

Please reach out to us here with your feedback.

Return to Help Center Home