Skip to content

Commit 5fd8a54

Browse files
committed
0.10.3 announced
1 parent ce2bb56 commit 5fd8a54

4 files changed

Lines changed: 108 additions & 4 deletions

File tree

assets/img/0_10_3.png

2.4 MB
Loading
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
author: Uitsmijter Team
3+
title: "Uitsmijter 0.10.3: Dynamic Scope Assignment"
4+
description: "Version 0.10.3 introduces provider-driven scope enrichment, enabling authentication providers to assign user-specific permissions dynamically during login."
5+
date: 2025-12-14
6+
draft: false
7+
tags: ["Release", "OAuth", "Scopes", "Authorization", "Security"]
8+
thumbnail:
9+
url: img/0_10_3.png
10+
author: ChatGPT
11+
---
12+
13+
# Uitsmijter 0.10.3: Dynamic Scope Assignment
14+
15+
Imagine you're managing a software development platform with hundreds of users across different teams. Some users are project managers who need to view reports and manage team assignments. Others are developers who need to commit code and create issues. Your authentication system knows exactly who has permission to do what, stored in your user database or calculated from group memberships. But here's the problem: how do you get that information into the OAuth tokens your applications use for authorization?
16+
17+
Traditional OAuth implementations force you to make an uncomfortable choice. Either you request the same static set of scopes for everyone and build complex authorization logic into every application, or you create dozens of different OAuth clients with different scope configurations. Neither option feels right. What you really want is for the authentication system that already knows about user permissions to simply tell your applications what each user can do. That's exactly what Uitsmijter 0.10.3 makes possible.
18+
19+
## When Static Scopes Stop Working
20+
21+
OAuth scopes were designed to be straightforward. An application asks for specific permissions like "read your email" or "access your profile," the user sees what's being requested, and those permissions are encoded into a token. This model works beautifully for consumer applications where permissions are relatively simple and uniform. But enterprise applications are different. The same application might need completely different permissions depending on who's logging in. A project management tool doesn't just need "access projects," it needs to know whether you can create, edit, or delete them.
22+
23+
The traditional solution handles this mismatch outside the OAuth flow. Applications request a generic set of scopes during authentication, then make additional API calls to figure out what the user can actually do. They might query a permissions service or check group memberships. This works, but it means every application you build has to implement the same authorization logic. You end up with permissions checks scattered across dozens of services. When someone's role changes, you hope all those systems stay in sync.
24+
25+
Version 0.10.3 takes a different approach. Instead of keeping authentication and authorization logic separate, it lets your JavaScript authentication provider directly communicate user permissions through the OAuth flow. When someone logs in, your provider doesn't just return "this person is authenticated," it returns "this person is authenticated with these specific permissions." Those permissions flow through the OAuth process and end up encoded directly in the JWT token, where every application can see them.
26+
27+
## How Scope Enrichment Works
28+
29+
Your authentication provider knows more about the user than just their password. It knows their role, their group memberships, which projects they're assigned to, and any other information stored in your user directory. With provider scope enrichment, that knowledge continues through to authorization.
30+
31+
When you implement a JavaScript authentication provider in Uitsmijter, you write a class with methods that handle the login process. Version 0.10.3 adds the ability to return scopes. After authenticating credentials, your provider can include a `scopes` property in its response. This might be a simple list based on the user's role, or it might be calculated dynamically by querying a database or checking group memberships.
32+
33+
Consider our software development platform. When a project manager logs in, your provider authenticates their credentials, looks up their role, and returns scopes like `project:manage` and `team:view`. When a developer logs in with the same application, the same authentication code runs but returns `code:commit` and `issue:create` instead. The OAuth client application doesn't need to know anything about roles. It requests the scopes it needs, and Uitsmijter merges those requested scopes with the permissions your provider assigned.
34+
35+
This merging happens automatically and securely. Uitsmijter takes the scopes requested by the client and the scopes returned by your provider, filters both through security controls, and combines them into a final set that appears in the JWT token. Your applications can then make authorization decisions based on that `scope` claim without calling back to any service or implementing role-based logic themselves.
36+
37+
## Security Through Two-Tier Filtering
38+
39+
Allowing authentication providers to assign scopes raises important security questions. What prevents a misconfigured provider from assigning administrative scopes to everyone? How do you ensure that applications only receive the scopes they're supposed to work with? Version 0.10.3 addresses these concerns through a two-tier filtering system.
40+
41+
The first tier is the client scope configuration, which has existed in Uitsmijter since the beginning. When you configure an OAuth client, you specify which scopes that client is allowed to request. If your project management application is configured with scopes like `openid`, `email`, and `profile`, then users can only receive those scopes in their tokens. Even if the application tries to request `admin:all` or your provider tries to assign `delete:everything`, those scopes won't make it into the token because they're not on the client's whitelist.
42+
43+
The second tier is new in version 0.10.3: the `allowedProviderScopes` configuration field. This controls which scopes your authentication provider is permitted to add. When you configure a client with `allowedProviderScopes` set to `user:*` and `project:*`, you're saying this application can receive any user-related or project-related scopes that the provider assigns, but nothing else. If your provider tries to assign `admin:delete`, that scope gets filtered out because it doesn't match the allowed patterns.
44+
45+
Both filters apply independently before the final scope list is assembled. Client-requested scopes pass through the `scopes` whitelist, while provider-assigned scopes pass through the `allowedProviderScopes` whitelist. By default, if you don't configure `allowedProviderScopes` at all, clients simply don't receive any provider-assigned scopes. This ensures secure defaults while making the new capability available when you explicitly enable it.
46+
47+
## Wildcards and Flexible Permission Structures
48+
49+
Managing scope configurations would be tedious if you had to enumerate every possible permission value. In real-world systems, you might have scopes like `project:123:edit` or `team:engineering:manage` based on resource IDs or organizational structures. Maintaining explicit lists of all these possibilities isn't practical.
50+
51+
Both the `scopes` and `allowedProviderScopes` fields support wildcard patterns. When you configure `user:*`, you're allowing any scope that starts with `user:`, regardless of what comes after. The wildcard matching makes it practical to use fine-grained, resource-specific scopes without turning your client configuration into an unmanageable list.
52+
53+
This flexibility is particularly valuable in multi-tenant environments where resource IDs appear in scopes. Your provider can assign scopes that precisely describe what a user can do, like `project:research-alpha:edit` or `department:engineering:budget:view`, and your client configuration can allow entire categories of those scopes with simple wildcard patterns.
54+
55+
## Beyond Scopes: Additional Improvements
56+
57+
While provider scope enrichment is the headline feature, version 0.10.3 includes several other improvements. Traefik 3 is now supported by default, reflecting the latest version of the popular reverse proxy that Uitsmijter integrates with. Traefik 2 continues to work with a simple configuration flag.
58+
59+
The default index page now shows the logged-in user's profile information and includes a logout button. This makes a difference when testing authentication flows or demonstrating the system to stakeholders. You can see at a glance who's logged in and easily sign out to test different user scenarios.
60+
61+
For developers building custom login experiences, the `PageProperties` object available in login templates now includes a `requestedScopes` property. This provides the information needed to build OAuth consent screens where users can review permissions, should your use case require it.
62+
63+
## Getting Started
64+
65+
Adding provider scope enrichment to your deployment is straightforward. Start by updating your JavaScript authentication provider to return a `scopes` property from the login method. This can be as simple as returning a fixed list based on user roles, or as complex as running database queries to calculate permissions.
66+
67+
Next, update your Client resource configurations to include the `allowedProviderScopes` field. Start with specific patterns that match the scopes your provider assigns. If you're returning scopes like `user:list` and `user:create`, configure `allowedProviderScopes: ["user:*"]`. You can refine these patterns over time as you add more scopes.
68+
69+
Here's an example client configuration:
70+
71+
```yaml
72+
apiVersion: uitsmijter.io/v1
73+
kind: Client
74+
metadata:
75+
name: my-app
76+
spec:
77+
scopes: ["openid", "email", "profile"]
78+
allowedProviderScopes: ["user:*", "project:*"]
79+
```
80+
81+
Once configured, scopes will automatically appear in the `scope` claim of JWT tokens. Your applications can read this claim and make authorization decisions based on its contents. Instead of calling back to a permissions API, they can simply check whether the token contains the scope they need.
82+
83+
## Looking Forward
84+
85+
Version 0.10.3 represents an evolution in how Uitsmijter handles authorization. By allowing authentication providers to directly communicate user permissions through the OAuth flow, it eliminates the gap between knowing who someone is and knowing what they're allowed to do. The two-tier filtering system ensures this capability doesn't compromise security while giving providers the flexibility to assign permissions dynamically.
86+
87+
This foundation opens up new possibilities for how you build and integrate applications. Instead of implementing authorization logic in every service, you can centralize permission calculations in your authentication provider. As your organization's permission model evolves, you update the provider logic once rather than modifying dozens of applications. The scope enrichment system in Uitsmijter 0.10.3 makes authorization as dynamic and centralized as authentication has always been.
88+
89+
## Resources
90+
91+
- [Documentation](https://docs.uitsmijter.io/)
92+
- [GitHub Repository](https://github.com/uitsmijter/Uitsmijter)
93+
- [Community Discussion](https://discourse.uitsmijter.io)

hugo_stats.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,17 @@
182182
"p-2",
183183
"p-3",
184184
"p-4",
185+
"page-item",
186+
"page-link",
187+
"pagination",
188+
"pagination-terse",
185189
"pb-5",
186190
"position-fixed",
187191
"position-relative",
188192
"post-date",
189193
"previous",
190194
"ps-1",
195+
"pt-3",
191196
"pt-5",
192197
"px-4",
193198
"px-xxl-0",
@@ -244,6 +249,7 @@
244249
"after-operational-clarity",
245250
"articles",
246251
"before-the-visibility-gap",
252+
"beyond-scopes-additional-improvements",
247253
"btn-webshare",
248254
"building-on-solid-ground",
249255
"chapter-1-one-service-one-secret",
@@ -252,9 +258,7 @@
252258
"chapter-4-bread-and-butter-inc-migrates-to-rs256",
253259
"chapter-5-why-uitsmijter-chose-rs256-as-default",
254260
"cloud-native-architecture",
255-
"cloud-native-by-design",
256261
"cloud-native-by-design-not-retrofitted",
257-
"cloud-native-by-designnot-retrofitted",
258262
"conclusion",
259263
"customising-solutions-for-smes",
260264
"discourse-comments",
@@ -267,10 +271,12 @@
267271
"getting-started",
268272
"getting-started-with-0100",
269273
"heres-whats-new",
274+
"how-scope-enrichment-works",
270275
"innovations",
271276
"join-the-conversation",
272277
"jwks-the-public-key-distribution-system",
273278
"key-generation-specifications",
279+
"looking-forward",
274280
"migrating-existing-deployments",
275281
"navbar-0-collapse",
276282
"navigating-digital-transformation-overcoming-legacy-challenges-for-smes",
@@ -279,8 +285,10 @@
279285
"real-time-automatic-updates",
280286
"redis-high-availability",
281287
"resource-server-examples",
288+
"resources",
282289
"resources--community",
283290
"scaling-to-new-heights",
291+
"security-through-two-tier-filtering",
284292
"solution-approaches",
285293
"standardisation-and-sovereignty",
286294
"step-1-update-the-tenant-configuration",
@@ -309,6 +317,7 @@
309317
"toast-message-email-4",
310318
"toc-collapse",
311319
"uitsmijter-0100-foundation-for-the-future",
320+
"uitsmijter-0103-dynamic-scope-assignment",
312321
"uitsmijter-096-release-new-features-improvements-and-fixes",
313322
"understanding-the-technical-details",
314323
"unleashing-flexibility-and-agility-in-development",
@@ -318,9 +327,11 @@
318327
"whats-coming-in-0100",
319328
"whats-new-in-uitsmijter-010",
320329
"whats-next",
330+
"when-static-scopes-stop-working",
321331
"why-jwks-matters-for-production",
322332
"why-this-matters",
323-
"why-we-built-this-from-scratch"
333+
"why-we-built-this-from-scratch",
334+
"wildcards-and-flexible-permission-structures"
324335
]
325336
}
326337
}

layouts/partials/assets/pagination.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
{{- if gt $page.Paginator.TotalPages 1 }}
2525
<nav aria-label="{{ T "paginationNav" }}">
2626
<ul class="pagination pagination-{{ $format }} justify-content-center">
27-
{{- partial (printf "partials/inline/pagination/%s" $format) $page }}
27+
{{- partial (printf "inline/pagination/%s" $format) $page }}
2828
</ul>
2929
</nav>
3030
{{- end }}

0 commit comments

Comments
 (0)