Skip to content

Commit aa336ee

Browse files
committed
add preferred_username profile field and use the value in new oidc claim preferred_username served under the profile scope
1 parent cada588 commit aa336ee

6 files changed

Lines changed: 44 additions & 4 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,12 @@ The BornHack website can act as an OIDC IDP. You are welcome to use it for your
168168

169169
### OIDC User Claims
170170

171-
The supported standard and custom OIDC user claims can be seen in `bornhack/oauth_validators.py` https://github.com/bornhack/bornhack-website/blob/master/src/bornhack/oauth_validators
171+
The supported standard and custom OIDC user claims can be seen in `bornhack/oauth_validators.py` https://github.com/bornhack/bornhack-website/blob/master/src/bornhack/oauth_validators.py
172172

173173

174174
### OIDC Scopes
175175

176-
Supported oauth2 scopes are split between standard OIDC claim scopes, custom OIDC claim scopes, and API scopes. The current list of supported scopes can be seen in the `OAUTH2_PROVIDER["SCOPES"]` dict in `bornhack/settings.py` https://github.com/bornhack/bornhack-website/blob/master/src/bornhack/settings.py
176+
Supported oauth2 scopes are divided into standard OIDC claim scopes, custom OIDC claim scopes, and API scopes. The current list of supported scopes can be seen in the `OAUTH2_PROVIDER["SCOPES"]` dict in `bornhack/settings.py` https://github.com/bornhack/bornhack-website/blob/master/src/bornhack/settings.py
177177

178178

179179
## Notes

src/bornhack/oauth_validators.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class BornhackOAuth2Validator(OAuth2Validator):
1717
"email_verified": "email",
1818
"phone_number": "phone",
1919
"phone_number_verified": "phone",
20+
"preferred_username": "profile",
2021
"updated_at": "profile",
2122
# the custom user claims we support, and the (mostly custom) scopes they require
2223
"bornhack:v2:description": "profile",
@@ -46,6 +47,7 @@ def get_additional_claims(self, request) -> dict[str, str | list[dict[str, str]]
4647
if request.user.is_anonymous:
4748
return claims
4849

50+
# these claims are always available
4951
claims.update(
5052
{
5153
# standard OIDC claims
@@ -84,11 +86,15 @@ def get_additional_claims(self, request) -> dict[str, str | list[dict[str, str]]
8486
# include phonenumber?
8587
if request.user.profile.phonenumber:
8688
claims["phone_number"] = request.user.profile.phonenumber
87-
claims["phone_number_verified"] = True
8889

8990
# include profile description?
9091
if request.user.profile.description:
9192
claims["bornhack:v2:description"] = request.user.profile.description
93+
94+
# include preferred_username?
95+
if request.user.profile.preferred_username:
96+
claims["preferred_username"] = request.user.profile.preferred_username
97+
9298
return claims
9399

94100
def get_discovery_claims(self, request) -> list[str]:
@@ -103,6 +109,7 @@ def get_discovery_claims(self, request) -> list[str]:
103109
"nickname",
104110
"phone_number",
105111
"phone_number_verified",
112+
"preferred_username",
106113
"sub",
107114
"updated_at",
108115
# custom user claims
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.20 on 2025-04-28 15:00
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('profiles', '0017_alter_profile_phonenumber'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='profile',
15+
name='preferred_username',
16+
field=models.SlugField(blank=True, help_text="When using your BornHack account to login to other sites with OIDC this value is served as the OIDC standard claim 'preferred_username'. You can set this to the username you would prefer to use on remote sites where you login with your BornHack account."),
17+
),
18+
]

src/profiles/models.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ class Meta:
6767
help_text="The phonenumber you can be reached on. This field can be updated automatically when registering a DECT number in the phonebook.",
6868
)
6969

70-
# default to near general camping
7170
location = PointField(
7271
blank=True,
7372
null=True,
7473
help_text="Your location at BornHack. This value is available on public maps.",
7574
)
7675

76+
preferred_username = models.SlugField(
77+
blank=True,
78+
max_length=50,
79+
help_text="When using your BornHack account to login to other sites with OIDC this value is served as the OIDC standard claim 'preferred_username'. You can set this to the username you would prefer to use on remote sites where you login with your BornHack account.",
80+
)
81+
7782
@property
7883
def email(self):
7984
return self.user.email

src/profiles/templates/profile_detail.html

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,15 @@ <h4>Your information</h4>
9191
</td>
9292
</tr>
9393

94+
<tr>
95+
<td>
96+
<b>OIDC Preferred Username</b><br />
97+
<small>When using BornHack as an IDP this value is available to remote sites with the <code>profile</code> scope. Set this to the username you prefer to use on the remote sites where you login with your BornHack account.</small>
98+
</td>
99+
<td>
100+
{{ profile.preferred_username|default:"N/A" }}
101+
</td>
102+
</tr>
94103
</table>
95104
</div>
96105
</div>

src/profiles/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class ProfileUpdate(LoginRequiredMixin, UpdateView):
3232
"location",
3333
"nickserv_username",
3434
"theme",
35+
"preferred_username",
3536
]
3637
success_url = reverse_lazy("profiles:detail")
3738
template_name = "profile_form.html"

0 commit comments

Comments
 (0)