providers/oauth2: show id_token issues for refresh token

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-06-02 22:04:19 +02:00
parent 4d773274d4
commit cec47c3cfc
8 changed files with 144 additions and 20 deletions

View file

@ -1,8 +1,11 @@
"""OAuth2Provider API Views""" """OAuth2Provider API Views"""
from dataclasses import asdict
from json import dumps
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from guardian.utils import get_anonymous_user from guardian.utils import get_anonymous_user
from rest_framework import mixins from rest_framework import mixins
from rest_framework.fields import CharField, ListField from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
@ -27,6 +30,30 @@ class ExpiringBaseGrantModelSerializer(ModelSerializer, MetaNameSerializer):
depth = 2 depth = 2
class RefreshTokenModelSerializer(ExpiringBaseGrantModelSerializer):
"""Serializer for BaseGrantModel and RefreshToken"""
id_token = SerializerMethodField()
def get_id_token(self, instance: RefreshToken) -> str:
"""Get the token's id_token as JSON String"""
return dumps(asdict(instance.id_token), indent=4)
class Meta:
model = RefreshToken
fields = [
"pk",
"provider",
"user",
"is_expired",
"expires",
"scope",
"id_token",
]
depth = 2
class AuthorizationCodeViewSet( class AuthorizationCodeViewSet(
mixins.RetrieveModelMixin, mixins.RetrieveModelMixin,
mixins.DestroyModelMixin, mixins.DestroyModelMixin,
@ -61,7 +88,7 @@ class RefreshTokenViewSet(
"""RefreshToken Viewset""" """RefreshToken Viewset"""
queryset = RefreshToken.objects.all() queryset = RefreshToken.objects.all()
serializer_class = ExpiringBaseGrantModelSerializer serializer_class = RefreshTokenModelSerializer
filterset_fields = ["user", "provider"] filterset_fields = ["user", "provider"]
ordering = ["provider", "expires"] ordering = ["provider", "expires"]
filter_backends = [ filter_backends = [

View file

@ -6,13 +6,13 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('authentik_tenants', '0002_default'), ("authentik_tenants", "0002_default"),
] ]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='tenant', model_name="tenant",
name='branding_favicon', name="branding_favicon",
field=models.TextField(default='/static/dist/assets/icons/icon.png'), field=models.TextField(default="/static/dist/assets/icons/icon.png"),
), ),
] ]

View file

@ -25,9 +25,7 @@ class Tenant(models.Model):
branding_logo = models.TextField( branding_logo = models.TextField(
default="/static/dist/assets/icons/icon_left_brand.svg" default="/static/dist/assets/icons/icon_left_brand.svg"
) )
branding_favicon = models.TextField( branding_favicon = models.TextField(default="/static/dist/assets/icons/icon.png")
default="/static/dist/assets/icons/icon.png"
)
flow_authentication = models.ForeignKey( flow_authentication = models.ForeignKey(
Flow, null=True, on_delete=models.SET_NULL, related_name="tenant_authentication" Flow, null=True, on_delete=models.SET_NULL, related_name="tenant_authentication"

View file

@ -4772,7 +4772,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/PaginatedExpiringBaseGrantModelList' $ref: '#/components/schemas/PaginatedRefreshTokenModelList'
description: '' description: ''
'400': '400':
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
@ -4799,7 +4799,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
$ref: '#/components/schemas/ExpiringBaseGrantModel' $ref: '#/components/schemas/RefreshTokenModel'
description: '' description: ''
'400': '400':
$ref: '#/components/schemas/ValidationError' $ref: '#/components/schemas/ValidationError'
@ -20827,6 +20827,41 @@ components:
required: required:
- pagination - pagination
- results - results
PaginatedRefreshTokenModelList:
type: object
properties:
pagination:
type: object
properties:
next:
type: number
previous:
type: number
count:
type: number
current:
type: number
total_pages:
type: number
start_index:
type: number
end_index:
type: number
required:
- next
- previous
- count
- current
- total_pages
- start_index
- end_index
results:
type: array
items:
$ref: '#/components/schemas/RefreshTokenModel'
required:
- pagination
- results
PaginatedReputationPolicyList: PaginatedReputationPolicyList:
type: object type: object
properties: properties:
@ -24150,6 +24185,38 @@ components:
required: required:
- to - to
- type - type
RefreshTokenModel:
type: object
description: Serializer for BaseGrantModel and RefreshToken
properties:
pk:
type: integer
readOnly: true
title: ID
provider:
$ref: '#/components/schemas/OAuth2Provider'
user:
$ref: '#/components/schemas/User'
is_expired:
type: boolean
readOnly: true
expires:
type: string
format: date-time
scope:
type: array
items:
type: string
id_token:
type: string
readOnly: true
required:
- id_token
- is_expired
- pk
- provider
- scope
- user
ReputationPolicy: ReputationPolicy:
type: object type: object
description: Reputation Policy Serializer description: Reputation Policy Serializer

View file

@ -1,19 +1,26 @@
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../table/Table"; import { Table, TableColumn } from "../table/Table";
import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";
import "../forms/DeleteForm"; import "../forms/DeleteForm";
import { PAGE_SIZE } from "../../constants"; import { PAGE_SIZE } from "../../constants";
import { ExpiringBaseGrantModel, Oauth2Api } from "authentik-api"; import { RefreshTokenModel, Oauth2Api } from "authentik-api";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@customElement("ak-user-oauth-refresh-list") @customElement("ak-user-oauth-refresh-list")
export class UserOAuthRefreshList extends Table<ExpiringBaseGrantModel> { export class UserOAuthRefreshList extends Table<RefreshTokenModel> {
expandable = true;
@property({ type: Number }) @property({ type: Number })
userId?: number; userId?: number;
apiEndpoint(page: number): Promise<AKResponse<ExpiringBaseGrantModel>> { static get styles(): CSSResult[] {
return super.styles.concat(PFFlex);
}
apiEndpoint(page: number): Promise<AKResponse<RefreshTokenModel>> {
return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensList({ return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensList({
user: this.userId, user: this.userId,
ordering: "expires", ordering: "expires",
@ -33,7 +40,24 @@ export class UserOAuthRefreshList extends Table<ExpiringBaseGrantModel> {
]; ];
} }
row(item: ExpiringBaseGrantModel): TemplateResult[] { renderExpanded(item: RefreshTokenModel): TemplateResult {
return html`
<td role="cell" colspan="4">
<div class="pf-c-table__expandable-row-content">
<div class="pf-l-flex">
<div class="pf-l-flex__item">
<h3>${t`ID Token`}</h3>
<pre>${item.idToken}</pre>
</div>
</div>
</div>
</td>
<td></td>
<td></td>
<td></td>`;
}
row(item: RefreshTokenModel): TemplateResult[] {
return [ return [
html`<a href="#/core/providers/${item.provider?.pk}"> html`<a href="#/core/providers/${item.provider?.pk}">
${item.provider?.name} ${item.provider?.name}

View file

@ -1717,6 +1717,10 @@ msgstr "How many attempts a user has before the flow is canceled. To lock the us
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
#: src/elements/oauth/UserRefreshList.ts
msgid "ID Token"
msgstr "ID Token"
#: src/pages/policies/reputation/IPReputationListPage.ts #: src/pages/policies/reputation/IPReputationListPage.ts
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"

View file

@ -1709,6 +1709,10 @@ msgstr ""
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#:
msgid "ID Token"
msgstr ""
#: #:
msgid "IP" msgid "IP"
msgstr "" msgstr ""

View file

@ -197,7 +197,7 @@ export class UserViewPage extends LitElement {
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog
targetModelPk=${this.user.pk || 0} targetModelPk=${this.user.pk}
targetModelApp="authentik_core" targetModelApp="authentik_core"
targetModelName="user"> targetModelName="user">
</ak-object-changelog> </ak-object-changelog>
@ -207,7 +207,7 @@ export class UserViewPage extends LitElement {
<section slot="page-consent" data-tab-title="${t`Explicit Consent`}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <section slot="page-consent" data-tab-title="${t`Explicit Consent`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-user-consent-list userId=${(this.user.pk || 0)}> <ak-user-consent-list userId=${(this.user.pk)}>
</ak-user-consent-list> </ak-user-consent-list>
</div> </div>
</div> </div>
@ -215,7 +215,7 @@ export class UserViewPage extends LitElement {
<section slot="page-oauth-code" data-tab-title="${t`OAuth Authorization Codes`}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <section slot="page-oauth-code" data-tab-title="${t`OAuth Authorization Codes`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-user-oauth-code-list userId=${this.user.pk || 0}> <ak-user-oauth-code-list userId=${this.user.pk}>
</ak-user-oauth-code-list> </ak-user-oauth-code-list>
</div> </div>
</div> </div>
@ -223,7 +223,7 @@ export class UserViewPage extends LitElement {
<section slot="page-oauth-refresh" data-tab-title="${t`OAuth Refresh Codes`}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <section slot="page-oauth-refresh" data-tab-title="${t`OAuth Refresh Codes`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-user-oauth-refresh-list userId=${this.user.pk || 0}> <ak-user-oauth-refresh-list userId=${this.user.pk}>
</ak-user-oauth-refresh-list> </ak-user-oauth-refresh-list>
</div> </div>
</div> </div>