Authentication
GQLForge provides built-in authentication and authorization through directives and linked provider files.
Authentication Providers
Use the @link directive to register an authentication provider.
HTTP Basic (Htpasswd)
schema @link(type: Htpasswd, src: "./htpasswd") {
query: Query
}
The referenced file uses the standard htpasswd format:
admin:$apr1$xyz$hashedpassword
viewer:$apr1$abc$anotherpassword
JSON Web Keys (JWKS)
schema @link(type: Jwks, src: "https://auth.example.com/.well-known/jwks.json") {
query: Query
}
GQLForge fetches the JWKS endpoint and validates JWT tokens from incoming requests automatically.
The @protected Directive
Apply @protected to restrict access to authenticated users.
Field-Level Protection
type Query {
publicPosts: [Post] @http(url: "https://api.example.com/posts")
myProfile: User @http(url: "https://api.example.com/me") @protected
}
Only authenticated requests can resolve myProfile. Unauthenticated requests receive an error.
Type-Level Protection
type AdminData @protected {
revenue: Float
activeUsers: Int
}
When @protected is placed on a type, every field that returns that type requires authentication.
Expression-Based Access Control
The @protected directive accepts an expr parameter for fine-grained authorization based on JWT claims and query arguments.
type Query {
adminDashboard: Dashboard
@http(url: "https://api.example.com/admin/dashboard")
@protected(expr: "claims.role == 'admin'")
user(userId: ID!): User
@http(url: "https://api.example.com/users/{{.args.userId}}")
@protected(expr: "claims.sub == args.userId")
}
The expression is evaluated after token validation. If it returns false, the request is rejected with an authorization error.
For the full expression syntax and supported operators, see the @protected directive reference.
JWT Claims in Templates
When using JWKS authentication, verified JWT claims are available in Mustache templates via .claims. This enables dynamic URL construction based on the authenticated user’s identity.
type Query {
myPosts: [Post] @http(url: "https://api.example.com/posts?author={{.claims.sub}}") @protected
}
In this example, {{.claims.sub}} is replaced with the sub claim from the JWT, so each user only fetches their own posts.
For more details on available context variables, see the Context Object page.
How It Works
- GQLForge reads the
Authorizationheader from incoming requests. - The token or credentials are validated against the configured provider (Htpasswd or JWKS).
- For JWKS providers, the decoded JWT claims are stored in the request context, making them available via
claims.*in expressions and{{.claims.*}}in templates. - If the
@protecteddirective specifies anexpr, the expression is evaluated against the request context. If it returnsfalse, the request is rejected with an authorization error. - If validation succeeds (and the expression passes, if specified), the request proceeds normally.
- If validation fails, fields marked with
@protectedreturn an authentication error.
Combining Providers
You can link multiple providers in the same schema. GQLForge attempts validation against each provider in order until one succeeds.
schema
@link(type: Jwks, src: "https://auth.example.com/.well-known/jwks.json")
@link(type: Htpasswd, src: "./htpasswd") {
query: Query
}