providers/oauth2: add device flow (#3334)
* start device flow Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * web: fix inconsistent app filtering Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add tenant device code flow Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add throttling to device code view Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * somewhat unrelated changes Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add initial device code entry flow Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add finish stage Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * it works Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add support for verification_uri_complete Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add some tests Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add more tests Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add docs Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		
							
								
								
									
										80
									
								
								web/src/flow/providers/oauth2/DeviceCode.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								web/src/flow/providers/oauth2/DeviceCode.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| import "@goauthentik/elements/EmptyState"; | ||||
| import "@goauthentik/elements/forms/FormElement"; | ||||
| import "@goauthentik/flow/FormStatic"; | ||||
| import { BaseStage } from "@goauthentik/flow/stages/base"; | ||||
|  | ||||
| import { t } from "@lingui/macro"; | ||||
|  | ||||
| import { CSSResult, TemplateResult, html } from "lit"; | ||||
| import { customElement } from "lit/decorators.js"; | ||||
|  | ||||
| import AKGlobal from "@goauthentik/common/styles/authentik.css"; | ||||
| import PFButton from "@patternfly/patternfly/components/Button/button.css"; | ||||
| import PFForm from "@patternfly/patternfly/components/Form/form.css"; | ||||
| import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; | ||||
| import PFLogin from "@patternfly/patternfly/components/Login/login.css"; | ||||
| import PFTitle from "@patternfly/patternfly/components/Title/title.css"; | ||||
| import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
|  | ||||
| import { | ||||
|     OAuthDeviceCodeChallenge, | ||||
|     OAuthDeviceCodeChallengeResponseRequest, | ||||
| } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-flow-provider-oauth2-code") | ||||
| export class OAuth2DeviceCode extends BaseStage< | ||||
|     OAuthDeviceCodeChallenge, | ||||
|     OAuthDeviceCodeChallengeResponseRequest | ||||
| > { | ||||
|     static get styles(): CSSResult[] { | ||||
|         return [PFBase, PFLogin, PFForm, PFFormControl, PFTitle, PFButton, AKGlobal]; | ||||
|     } | ||||
|  | ||||
|     render(): TemplateResult { | ||||
|         if (!this.challenge) { | ||||
|             return html`<ak-empty-state ?loading="${true}" header=${t`Loading`}> </ak-empty-state>`; | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|                 <form | ||||
|                     class="pf-c-form" | ||||
|                     @submit=${(e: Event) => { | ||||
|                         this.submitForm(e); | ||||
|                     }} | ||||
|                 > | ||||
|                     <p>${t`Enter the code shown on your device.`}</p> | ||||
|                     <ak-form-element | ||||
|                         label="${t`Code`}" | ||||
|                         ?required="${true}" | ||||
|                         class="pf-c-form__group" | ||||
|                         .errors=${(this.challenge?.responseErrors || {})["code"]} | ||||
|                     > | ||||
|                         <!-- @ts-ignore --> | ||||
|                         <input | ||||
|                             type="text" | ||||
|                             name="code" | ||||
|                             inputmode="numeric" | ||||
|                             pattern="[0-9]*" | ||||
|                             placeholder="${t`Please enter your Code`}" | ||||
|                             autofocus="" | ||||
|                             autocomplete="off" | ||||
|                             class="pf-c-form-control" | ||||
|                             value="" | ||||
|                             required | ||||
|                         /> | ||||
|                     </ak-form-element> | ||||
|  | ||||
|                     <div class="pf-c-form__group pf-m-action"> | ||||
|                         <button type="submit" class="pf-c-button pf-m-primary pf-m-block"> | ||||
|                             ${t`Continue`} | ||||
|                         </button> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </div> | ||||
|             <footer class="pf-c-login__main-footer"> | ||||
|                 <ul class="pf-c-login__main-footer-links"></ul> | ||||
|             </footer>`; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								web/src/flow/providers/oauth2/DeviceCodeFinish.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								web/src/flow/providers/oauth2/DeviceCodeFinish.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | ||||
| import "@goauthentik/elements/EmptyState"; | ||||
| import "@goauthentik/flow/FormStatic"; | ||||
| import { BaseStage } from "@goauthentik/flow/stages/base"; | ||||
|  | ||||
| import { t } from "@lingui/macro"; | ||||
|  | ||||
| import { CSSResult, TemplateResult, html } from "lit"; | ||||
| import { customElement } from "lit/decorators.js"; | ||||
|  | ||||
| import AKGlobal from "@goauthentik/common/styles/authentik.css"; | ||||
| import PFForm from "@patternfly/patternfly/components/Form/form.css"; | ||||
| import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; | ||||
| import PFList from "@patternfly/patternfly/components/List/list.css"; | ||||
| import PFLogin from "@patternfly/patternfly/components/Login/login.css"; | ||||
| import PFTitle from "@patternfly/patternfly/components/Title/title.css"; | ||||
| import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
|  | ||||
| import { | ||||
|     OAuthDeviceCodeFinishChallenge, | ||||
|     OAuthDeviceCodeFinishChallengeResponseRequest, | ||||
| } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-flow-provider-oauth2-code-finish") | ||||
| export class DeviceCodeFinish extends BaseStage< | ||||
|     OAuthDeviceCodeFinishChallenge, | ||||
|     OAuthDeviceCodeFinishChallengeResponseRequest | ||||
| > { | ||||
|     static get styles(): CSSResult[] { | ||||
|         return [PFBase, PFLogin, PFForm, PFList, PFFormControl, PFTitle, AKGlobal]; | ||||
|     } | ||||
|  | ||||
|     render(): TemplateResult { | ||||
|         if (!this.challenge) { | ||||
|             return html`<ak-empty-state ?loading="${true}" header=${t`Loading`}> </ak-empty-state>`; | ||||
|         } | ||||
|         return html`<header class="pf-c-login__main-header"> | ||||
|                 <h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1> | ||||
|             </header> | ||||
|             <div class="pf-c-login__main-body"> | ||||
|                 <form class="pf-c-form"> | ||||
|                     <div class="pf-c-form__group"> | ||||
|                         <p> | ||||
|                             <i class="pf-icon pf-icon-ok"></i> | ||||
|                             ${t`You've successfully authenticated your device.`} | ||||
|                         </p> | ||||
|                         <hr /> | ||||
|                         <p>${t`You can close this tab now.`}</p> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </div> | ||||
|             <footer class="pf-c-login__main-footer"> | ||||
|                 <ul class="pf-c-login__main-footer-links"></ul> | ||||
|             </footer>`; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user