@nocobase/plugin-idp-oauth 2.2.0-beta.7 → 2.2.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/DevicePage.d.ts +11 -0
- package/dist/client/index.js +1 -1
- package/dist/client/locale.d.ts +1 -1
- package/dist/externalVersion.js +7 -7
- package/dist/locale/en-US.json +21 -1
- package/dist/locale/zh-CN.json +21 -1
- package/dist/node_modules/light-my-request/package.json +1 -1
- package/dist/node_modules/ms/package.json +1 -1
- package/dist/server/device-verification.d.ts +26 -0
- package/dist/server/device-verification.js +256 -0
- package/dist/server/interaction.d.ts +1 -0
- package/dist/server/interaction.js +26 -2
- package/dist/server/plugin.js +12 -0
- package/dist/server/provider-dispatch.js +75 -8
- package/dist/server/service.d.ts +2 -0
- package/dist/server/service.js +140 -4
- package/package.json +2 -2
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import React from 'react';
|
|
10
|
+
export declare const DevicePage: () => React.JSX.Element;
|
|
11
|
+
export default DevicePage;
|
package/dist/client/index.js
CHANGED
|
@@ -7,4 +7,4 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("antd"),require("react"),require("@nocobase/client"),require("react-router-dom")):"function"==typeof define&&define.amd?define("@nocobase/plugin-idp-oauth",["antd","react","@nocobase/client","react-router-dom"],t):"object"==typeof exports?exports["@nocobase/plugin-idp-oauth"]=t(require("antd"),require("react"),require("@nocobase/client"),require("react-router-dom")):e["@nocobase/plugin-idp-oauth"]=t(e.antd,e.react,e["@nocobase/client"],e["react-router-dom"])}(self,function(e,t,r,n){return function(){"use strict";var o={342:function(e){e.exports=r},59:function(t){t.exports=e},155:function(e){e.exports=t},442:function(e){e.exports=n}},i={};function a(e){var t=i[e];if(void 0!==t)return t.exports;var r=i[e]={exports:{}};return o[e](r,r.exports,a),r.exports}a.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(t,{a:t}),t},a.d=function(e,t){for(var r in t)a.o(t,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.g.importScripts&&(u=a.g.location+"");var u,c=a.g.document;if(!u&&c&&(c.currentScript&&"SCRIPT"===c.currentScript.tagName.toUpperCase()&&(u=c.currentScript.src),!u)){var l=c.getElementsByTagName("script");if(l.length)for(var s=l.length-1;s>-1&&(!u||!/^http(s?):/.test(u));)u=l[s--].src}if(!u)throw Error("Automatic publicPath is not supported in this browser");a.p=u.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");var p={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var r=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");r.indexOf("/static/plugins/@nocobase/plugin-idp-oauth/dist/client/")>=0&&(e=r.replace(/\/[^\/]+$/,"/"))}if(!e){var n=window.__webpack_public_path__||"";n&&("/"!==n.charAt(n.length-1)&&(n+="/"),e=n+"static/plugins/@nocobase/plugin-idp-oauth/dist/client/")}if(!e){var o=window.__nocobase_modern_client_prefix__||"v",i="/"+(o=String(o).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var u=window.location.pathname||"/",c=u.indexOf(i);e=c>=0?u.slice(0,c+1):"/"}e&&(e=e.replace(RegExp("/"+o+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/@nocobase/plugin-idp-oauth/dist/client/"}a.p=e}(),!function(){a.r(p),a.d(p,{default:function(){return _}});var e=a(342),t=a(59),r=a(155),n=a.n(r),o=a(442);function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}var u=function(){var e,r=(function(e){if(Array.isArray(e))return e}(e=(0,o.useSearchParams)())||function(e){var t,r,n=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var o=[],i=!0,a=!1;try{for(n=n.call(e);!(i=(t=n.next()).done)&&(o.push(t.value),1!==o.length);i=!0);}catch(e){a=!0,r=e}finally{try{i||null==n.return||n.return()}finally{if(a)throw r}}return o}}(e)||function(e){if(e){if("string"==typeof e)return i(e,1);var t=Object.prototype.toString.call(e).slice(8,-1);if("Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t)return Array.from(t);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return i(e,1)}}(e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0],a=r.get("error"),u=r.get("error_description"),c=r.get("iss");return n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Result,{status:"error",title:a||"Authentication failed",subTitle:u||void 0}),n().createElement(t.Space,{direction:"vertical",size:"middle",style:{width:"100%"}},c?n().createElement("div",null,n().createElement(t.Typography.Text,{type:"secondary"},"Issuer"),n().createElement("div",null,n().createElement(t.Typography.Text,{code:!0},c))):null))};function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function l(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){r(e);return}u.done?t(c):Promise.resolve(c).then(n,o)}function s(e){return function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){l(i,n,o,a,u,"next",e)}function u(e){l(i,n,o,a,u,"throw",e)}a(void 0)})}}function f(e,t){return null!=t&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}function d(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var i=[],a=!0,u=!1;try{for(o=o.call(e);!(a=(r=o.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){u=!0,n=e}finally{try{a||null==o.return||o.return()}finally{if(u)throw n}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function y(e,t){var r,n,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(r)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],n=0}finally{r=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function h(e,t){return f(e,Error)?e.message:t}var m=function(){var i=(0,e.useAPIClient)(),a=(0,e.useApp)(),u=(0,o.useNavigate)(),c=(0,o.useParams)(),l=d((0,r.useState)(!0),2),p=l[0],m=l[1],v=d((0,r.useState)(null),2),b=v[0],g=v[1],w=d((0,r.useState)(null),2),x=w[0],E=w[1],S=(0,r.useMemo)(function(){return c.uid?"main"===a.name?"idpOAuth/interaction/".concat(c.uid):"__app/".concat(a.name,"/idpOAuth/interaction/").concat(c.uid):null},[a.name,c.uid]),_=(0,r.useMemo)(function(){return c.uid?"/idp-oauth/interaction/".concat(c.uid):"/signin"},[c.uid]),O=(0,r.useCallback)(function(e,t){return s(function(){var r,n,o,a,c;return y(this,function(l){switch(l.label){case 0:if(!S)return g("Invalid interaction path"),m(!1),[2];return n=i.auth.getToken(),o=i.auth.getAuthenticator()||"basic",[4,i.request({url:S,method:e,skipNotify:!0,withCredentials:!0,data:"post"===e?t:void 0,headers:n?{Authorization:"Bearer ".concat(n),"X-Authenticator":o}:void 0})];case 1:if(null==(c=(null==(a=l.sent())||null==(r=a.data)?void 0:r.data)||(null==a?void 0:a.data))?void 0:c.redirectTo)return window.location.replace(c.redirectTo),[2];if((null==c?void 0:c.prompt)!=="login")return[3,4];if(!n)return u("/signin?redirect=".concat(encodeURIComponent(_)),{replace:!0}),[2];if("get"!==e)return[3,3];return[4,O("post")];case 2:return l.sent(),[2];case 3:return u("/signin?redirect=".concat(encodeURIComponent(_)),{replace:!0}),[2];case 4:return E(c),m(!1),[2]}})})()},[i,_,S,u]),j=(0,r.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return s(function(){return y(this,function(t){switch(t.label){case 0:m(!0),g(null),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,O("post",e?{cancel:1}:{submit:1})];case 2:return t.sent(),[3,4];case 3:return g(h(t.sent(),"Failed to submit interaction")),m(!1),[3,4];case 4:return[2]}})})()},[O]);return((0,r.useEffect)(function(){var e=!1;return s(function(){var t;return y(this,function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,O("get")];case 1:return r.sent(),[3,3];case 2:return t=r.sent(),e||(g(h(t,"Failed to load interaction")),m(!1)),[3,3];case 3:return[2]}})})(),function(){e=!0}},[O]),(0,r.useEffect)(function(){if((null==x?void 0:x.prompt)==="consent"&&!p){var e=function(e){if(!e.defaultPrevented){var t=e.target;if(null==t||!t.closest('input, textarea, select, [contenteditable="true"]')){if("Enter"===e.key&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey&&!e.altKey){var r=document.activeElement;if(f(r,HTMLButtonElement)||f(r,HTMLAnchorElement))return;e.preventDefault(),j(!1);return}"Escape"===e.key&&(e.preventDefault(),j(!0))}}};return window.addEventListener("keydown",e),function(){return window.removeEventListener("keydown",e)}}},[null==x?void 0:x.prompt,p,j]),p)?n().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},n().createElement(t.Spin,{style:{fontSize:72}})):b?n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Alert,{type:"error",message:b,showIcon:!0})):(null==x?void 0:x.prompt)==="consent"?n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Card,null,n().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},n().createElement("div",null,n().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},"Authorize application"),n().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},x.clientName||"Application"," requests access to your account.")),x.details?n().createElement(t.Alert,{type:"info",showIcon:!0,message:"Requested permissions",description:x.details}):null,n().createElement(t.Space,null,n().createElement(t.Button,{type:"primary",loading:p,onClick:function(){return j(!1)}},"Continue"),n().createElement(t.Button,{loading:p,onClick:function(){return j(!0)}},"Cancel"))))):n().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},n().createElement(t.Result,{title:"Redirecting...",subTitle:"Please wait while authorization continues."}))},v={};function b(e,t,r,n,o,i,a){try{var u=e[i](a),c=u.value}catch(e){r(e);return}u.done?t(c):Promise.resolve(c).then(n,o)}function g(e,t,r){return(g=S()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var o=new(Function.bind.apply(e,n));return r&&x(o,r.prototype),o}).apply(null,arguments)}function w(e){return(w=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function x(e,t){return(x=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function E(e){var t="function"==typeof Map?new Map:void 0;return(E=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return g(e,arguments,w(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),x(r,e)})(e)}function S(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(S=function(){return!!e})()}var _=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function r(){var e,t;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return e=r,t=arguments,e=w(e),function(e,t){var r;if(t&&("object"==((r=t)&&"u">typeof Symbol&&r.constructor===Symbol?"symbol":typeof r)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,S()?Reflect.construct(e,t||[],w(this).constructor):e.apply(this,t))}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&x(r,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var r,n,o,i={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(a,"next",{value:c(0)}),u(a,"throw",{value:c(1)}),u(a,"return",{value:c(2)}),"function"==typeof Symbol&&u(a,Symbol.iterator,{value:function(){return this}}),a;function c(u){return function(c){var l=[u,c];if(r)throw TypeError("Generator is already executing.");for(;a&&(a=0,l[0]&&(i=0)),i;)try{if(r=1,n&&(o=2&l[0]?n.return:l[0]?n.throw||((o=n.return)&&o.call(n),0):n.next)&&!(o=o.call(n,l[1])).done)return o;switch(n=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return i.label++,{value:l[1],done:!1};case 5:i.label++,n=l[1],l=[0];continue;case 7:l=i.ops.pop(),i.trys.pop();continue;default:if(!(o=(o=i.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){i=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){i.label=l[1];break}if(6===l[0]&&i.label<o[1]){i.label=o[1],o=l;break}if(o&&i.label<o[2]){i.label=o[2],i.ops.push(l);break}o[2]&&i.ops.pop(),i.trys.pop();continue}l=t.call(e,i)}catch(e){l=[6,e],n=0}finally{r=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return e=this,e.flowEngine.registerModels(v),e.router.add("idp-oauth.interaction",{path:"/idp-oauth/interaction/:uid",Component:m,skipAuthCheck:!0}),e.router.add("idp-oauth.error",{path:"/idp-oauth/error",Component:u,skipAuthCheck:!0}),[2]})},function(){var t=this,r=arguments;return new Promise(function(n,o){var i=e.apply(t,r);function a(e){b(i,n,o,a,u,"next",e)}function u(e){b(i,n,o,a,u,"throw",e)}a(void 0)})}).call(this)}}],function(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}(r.prototype,t),r}(E(e.Plugin))}(),p}()});
|
|
10
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("antd"),require("@nocobase/client"),require("react-router-dom"),require("@nocobase/flow-engine")):"function"==typeof define&&define.amd?define("@nocobase/plugin-idp-oauth",["react","antd","@nocobase/client","react-router-dom","@nocobase/flow-engine"],t):"object"==typeof exports?exports["@nocobase/plugin-idp-oauth"]=t(require("react"),require("antd"),require("@nocobase/client"),require("react-router-dom"),require("@nocobase/flow-engine")):e["@nocobase/plugin-idp-oauth"]=t(e.react,e.antd,e["@nocobase/client"],e["react-router-dom"],e["@nocobase/flow-engine"])}(self,function(e,t,n,r,o){return function(){"use strict";var a={342:function(e){e.exports=n},694:function(e){e.exports=o},59:function(e){e.exports=t},155:function(t){t.exports=e},442:function(e){e.exports=r}},i={};function u(e){var t=i[e];if(void 0!==t)return t.exports;var n=i[e]={exports:{}};return a[e](n,n.exports,u),n.exports}u.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return u.d(t,{a:t}),t},u.d=function(e,t){for(var n in t)u.o(t,n)&&!u.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},u.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),u.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},u.r=function(e){"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},u.g.importScripts&&(c=u.g.location+"");var c,l=u.g.document;if(!c&&l&&(l.currentScript&&"SCRIPT"===l.currentScript.tagName.toUpperCase()&&(c=l.currentScript.src),!c)){var s=l.getElementsByTagName("script");if(s.length)for(var p=s.length-1;p>-1&&(!c||!/^http(s?):/.test(c));)c=s[p--].src}if(!c)throw Error("Automatic publicPath is not supported in this browser");u.p=c.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/");var f={};return!function(){var e="",t="u">typeof document?document.currentScript:null;if(t&&t.src){var n=t.src.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"");n.indexOf("/static/plugins/@nocobase/plugin-idp-oauth/dist/client/")>=0&&(e=n.replace(/\/[^\/]+$/,"/"))}if(!e){var r=window.__webpack_public_path__||"";r&&("/"!==r.charAt(r.length-1)&&(r+="/"),e=r+"static/plugins/@nocobase/plugin-idp-oauth/dist/client/")}if(!e){var o=window.__nocobase_modern_client_prefix__||"v",a="/"+(o=String(o).replace(/^\/+|\/+$/g,"")||"v")+"/";if(!(e=window.__nocobase_public_path__||"")&&window.location&&window.location.pathname){var i=window.location.pathname||"/",c=i.indexOf(a);e=c>=0?i.slice(0,c+1):"/"}e&&(e=e.replace(RegExp("/"+o+"/?$"),"/")),e||(e="/"),"/"!==e.charAt(e.length-1)&&(e+="/"),e+="static/plugins/@nocobase/plugin-idp-oauth/dist/client/"}u.p=e}(),!function(){u.r(f),u.d(f,{default:function(){return B}});var e=u(342),t=u(59),n=u(155),r=u.n(n),o=u(442),a=u(694),i=JSON.parse('{"UU":"@nocobase/plugin-idp-oauth"}');function c(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function l(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function s(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){l(a,r,o,i,u,"next",e)}function u(e){l(a,r,o,i,u,"throw",e)}i(void 0)})}}function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var a=[],i=!0,u=!1;try{for(o=o.call(e);!(i=(n=o.next()).done)&&(a.push(n.value),!t||a.length!==t);i=!0);}catch(e){u=!0,r=e}finally{try{i||null==o.return||o.return()}finally{if(u)throw r}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return c(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return c(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function y(e,t){var n;return(null!=(n=Error)&&"u">typeof Symbol&&n[Symbol.hasInstance]?!!n[Symbol.hasInstance](e):e instanceof n)?e.message:t}var m=function(){var u,c=(0,e.useAPIClient)(),l=(0,e.useApp)(),f=(0,o.useLocation)(),m=(0,o.useNavigate)(),h=(u=(0,a.useFlowEngine)(),(0,n.useCallback)(function(e,t){return u.context.t(e,function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{},r=Object.keys(n);"function"==typeof Object.getOwnPropertySymbols&&(r=r.concat(Object.getOwnPropertySymbols(n).filter(function(e){return Object.getOwnPropertyDescriptor(n,e).enumerable}))),r.forEach(function(t){var r;r=n[t],t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r})}return e}({ns:[i.UU,"client"]},t))},[u])),v=p((0,o.useSearchParams)(),2),b=v[0],g=v[1],w=p((0,n.useState)(!0),2),E=w[0],x=w[1],S=p((0,n.useState)(!1),2),O=S[0],C=S[1],_=p((0,n.useState)(null),2),T=_[0],A=_[1],k=p((0,n.useState)(null),2),j=k[0],I=k[1],P=b.get("user_code")||void 0,B=(0,n.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",t=arguments.length>1?arguments[1]:void 0;return s(function(){var n,r;return d(this,function(o){switch(o.label){case 0:return[4,c.request({url:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return"".concat("main"===e?"":"__app/".concat(e,"/"),"idpOAuth/device/verification").concat(t)}(l.name,e),method:e?"post":"get",skipNotify:!0,params:e?void 0:{user_code:P},data:t})];case 1:return[2,(null==(r=o.sent())||null==(n=r.data)?void 0:n.data)||(null==r?void 0:r.data)]}})})()},[c,l.name,P]),q=(0,n.useCallback)(function(){return s(function(){var e;return d(this,function(t){switch(t.label){case 0:x(!0),A(null),t.label=1;case 1:return t.trys.push([1,3,4,5]),[4,B()];case 2:if(I(e=t.sent()),"login"===e.status){var n,r,o,a;return m("/signin?redirect=".concat(encodeURIComponent((n=f.pathname,r=f.search,a=(o=e.userCode||P)?"?user_code=".concat(encodeURIComponent(o)):r,"".concat(n).concat(a)))),{replace:!0}),[2]}return[3,5];case 3:return A(y(t.sent(),h("Failed to load device sign-in."))),[3,5];case 4:return x(!1),[7];case 5:return[2]}})})()},[f.pathname,f.search,m,B,h,P]);(0,n.useEffect)(function(){q()},[q]);var R=(0,n.useCallback)(function(e){var t=e.user_code,n=null==t?void 0:t.trim();n&&g({user_code:n})},[g]),M=(0,n.useCallback)(function(e){return s(function(){return d(this,function(t){switch(t.label){case 0:C(!0),A(null),t.label=1;case 1:return t.trys.push([1,3,4,5]),[4,B(e,{user_code:(null==j?void 0:j.userCode)||P})];case 2:return I(t.sent()),[3,5];case 3:return A(y(t.sent(),h("Failed to submit device sign-in."))),[3,5];case 4:return C(!1),[7];case 5:return[2]}})})()},[null==j?void 0:j.userCode,B,h,P]);if(E)return r().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},r().createElement(t.Spin,{style:{fontSize:72}}));if(T)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Alert,{type:"error",message:T,showIcon:!0}));if(!j||"missing_code"===j.status)return r().createElement("div",{style:{maxWidth:440,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},h("Device sign-in")),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h("Enter the code shown in your terminal to continue signing in."))),r().createElement(t.Form,{layout:"vertical",onFinish:R},r().createElement(t.Form.Item,{name:"user_code",rules:[{required:!0,message:h("Enter the device code.")}]},r().createElement(t.Input,{autoFocus:!0,size:"large",style:{textTransform:"uppercase"}})),r().createElement(t.Button,{type:"primary",htmlType:"submit",block:!0},h("Continue"))))));if("complete"===j.status)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"success",title:h("Device sign-in complete"),subTitle:h("Authorization is complete. You can return to the terminal."),extra:r().createElement(t.Button,{type:"primary",onClick:function(){return m("/")}},h("Back to home"))}));if("cancelled"===j.status)return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"warning",title:h("Device sign-in cancelled"),subTitle:h("The device sign-in request was cancelled.")}));if("pending"!==j.status){var F={not_found:h("The device code was not found."),expired:h("The device code has expired."),already_used:h("The device code has already been used.")};return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"error",title:h("Device sign-in failed"),subTitle:F[j.status]}))}return r().createElement("div",{style:{maxWidth:520,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},h("Confirm device")),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h("{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.",{clientName:j.clientName||h("Application")}))),r().createElement(t.Typography.Title,{level:2,style:{margin:0,letterSpacing:"0.08em",textAlign:"center"}},j.userCode),r().createElement(t.Space,null,r().createElement(t.Button,{type:"primary",loading:O,onClick:function(){return M(":approve")}},h("Continue")),r().createElement(t.Button,{loading:O,onClick:function(){return M(":cancel")}},h("Cancel"))))))};function h(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var v=function(){var e,n=(function(e){if(Array.isArray(e))return e}(e=(0,o.useSearchParams)())||function(e){var t,n,r=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var o=[],a=!0,i=!1;try{for(r=r.call(e);!(a=(t=r.next()).done)&&(o.push(t.value),1!==o.length);a=!0);}catch(e){i=!0,n=e}finally{try{a||null==r.return||r.return()}finally{if(i)throw n}}return o}}(e)||function(e){if(e){if("string"==typeof e)return h(e,1);var t=Object.prototype.toString.call(e).slice(8,-1);if("Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t)return Array.from(t);if("Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t))return h(e,1)}}(e)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())[0],a=n.get("error"),i=n.get("error_description"),u=n.get("iss");return r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{status:"error",title:a||"Authentication failed",subTitle:i||void 0}),r().createElement(t.Space,{direction:"vertical",size:"middle",style:{width:"100%"}},u?r().createElement("div",null,r().createElement(t.Typography.Text,{type:"secondary"},"Issuer"),r().createElement("div",null,r().createElement(t.Typography.Text,{code:!0},u))):null))};function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function g(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function w(e){return function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){g(a,r,o,i,u,"next",e)}function u(e){g(a,r,o,i,u,"throw",e)}i(void 0)})}}function E(e,t){return null!=t&&"u">typeof Symbol&&t[Symbol.hasInstance]?!!t[Symbol.hasInstance](e):e instanceof t}function x(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,o=null==e?null:"u">typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=o){var a=[],i=!0,u=!1;try{for(o=o.call(e);!(i=(n=o.next()).done)&&(a.push(n.value),!t||a.length!==t);i=!0);}catch(e){u=!0,r=e}finally{try{i||null==o.return||o.return()}finally{if(u)throw r}}return a}}(e,t)||function(e,t){if(e){if("string"==typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return b(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}function O(e,t){return E(e,Error)?e.message:t}var C=function(){var a=(0,e.useAPIClient)(),i=(0,e.useApp)(),u=(0,o.useNavigate)(),c=(0,o.useParams)(),l=x((0,n.useState)(!0),2),s=l[0],p=l[1],f=x((0,n.useState)(null),2),d=f[0],y=f[1],m=x((0,n.useState)(null),2),h=m[0],v=m[1],b=(0,n.useMemo)(function(){return c.uid?"main"===i.name?"idpOAuth/interaction/".concat(c.uid):"__app/".concat(i.name,"/idpOAuth/interaction/").concat(c.uid):null},[i.name,c.uid]),g=(0,n.useMemo)(function(){return c.uid?"/idp-oauth/interaction/".concat(c.uid):"/signin"},[c.uid]),C=(0,n.useCallback)(function(e,t){return w(function(){var n,r,o,i,c;return S(this,function(l){switch(l.label){case 0:if(!b)return y("Invalid interaction path"),p(!1),[2];return r=a.auth.getToken(),o=a.auth.getAuthenticator()||"basic",[4,a.request({url:b,method:e,skipNotify:!0,withCredentials:!0,data:"post"===e?t:void 0,headers:r?{Authorization:"Bearer ".concat(r),"X-Authenticator":o}:void 0})];case 1:if(null==(c=(null==(i=l.sent())||null==(n=i.data)?void 0:n.data)||(null==i?void 0:i.data))?void 0:c.redirectTo)return window.location.replace(c.redirectTo),[2];if((null==c?void 0:c.prompt)!=="login")return[3,4];if(!r)return u("/signin?redirect=".concat(encodeURIComponent(g)),{replace:!0}),[2];if("get"!==e)return[3,3];return[4,C("post")];case 2:return l.sent(),[2];case 3:return u("/signin?redirect=".concat(encodeURIComponent(g)),{replace:!0}),[2];case 4:return v(c),p(!1),[2]}})})()},[a,g,b,u]),_=(0,n.useCallback)(function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0];return w(function(){return S(this,function(t){switch(t.label){case 0:p(!0),y(null),t.label=1;case 1:return t.trys.push([1,3,,4]),[4,C("post",e?{cancel:1}:{submit:1})];case 2:return t.sent(),[3,4];case 3:return y(O(t.sent(),"Failed to submit interaction")),p(!1),[3,4];case 4:return[2]}})})()},[C]);return((0,n.useEffect)(function(){var e=!1;return w(function(){var t;return S(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,C("get")];case 1:return n.sent(),[3,3];case 2:return t=n.sent(),e||(y(O(t,"Failed to load interaction")),p(!1)),[3,3];case 3:return[2]}})})(),function(){e=!0}},[C]),(0,n.useEffect)(function(){if((null==h?void 0:h.prompt)==="consent"&&!s){var e=function(e){if(!e.defaultPrevented){var t=e.target;if(null==t||!t.closest('input, textarea, select, [contenteditable="true"]')){if("Enter"===e.key&&!e.shiftKey&&!e.ctrlKey&&!e.metaKey&&!e.altKey){var n=document.activeElement;if(E(n,HTMLButtonElement)||E(n,HTMLAnchorElement))return;e.preventDefault(),_(!1);return}"Escape"===e.key&&(e.preventDefault(),_(!0))}}};return window.addEventListener("keydown",e),function(){return window.removeEventListener("keydown",e)}}},[null==h?void 0:h.prompt,s,_]),s)?r().createElement("div",{style:{position:"fixed",inset:0,display:"flex",alignItems:"center",justifyContent:"center"}},r().createElement(t.Spin,{style:{fontSize:72}})):d?r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Alert,{type:"error",message:d,showIcon:!0})):(null==h?void 0:h.prompt)==="consent"?r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Card,null,r().createElement(t.Space,{direction:"vertical",size:"large",style:{width:"100%"}},r().createElement("div",null,r().createElement(t.Typography.Title,{level:3,style:{marginBottom:8}},"Authorize application"),r().createElement(t.Typography.Paragraph,{style:{marginBottom:0}},h.clientName||"Application"," requests access to your account.")),h.details?r().createElement(t.Alert,{type:"info",showIcon:!0,message:"Requested permissions",description:h.details}):null,r().createElement(t.Space,null,r().createElement(t.Button,{type:"primary",loading:s,onClick:function(){return _(!1)}},"Continue"),r().createElement(t.Button,{loading:s,onClick:function(){return _(!0)}},"Cancel"))))):r().createElement("div",{style:{maxWidth:640,margin:"48px auto",padding:"0 24px"}},r().createElement(t.Result,{title:"Redirecting...",subTitle:"Please wait while authorization continues."}))},_={};function T(e,t,n,r,o,a,i){try{var u=e[a](i),c=u.value}catch(e){n(e);return}u.done?t(c):Promise.resolve(c).then(r,o)}function A(e,t,n){return(A=P()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var o=new(Function.bind.apply(e,r));return n&&j(o,n.prototype),o}).apply(null,arguments)}function k(e){return(k=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function j(e,t){return(j=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function I(e){var t="function"==typeof Map?new Map:void 0;return(I=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return A(e,arguments,k(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),j(n,e)})(e)}function P(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(P=function(){return!!e})()}var B=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function n(){var e,t;if(!(this instanceof n))throw TypeError("Cannot call a class as a function");return e=n,t=arguments,e=k(e),function(e,t){var n;if(t&&("object"==((n=t)&&"u">typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,P()?Reflect.construct(e,t||[],k(this).constructor):e.apply(this,t))}return n.prototype=Object.create(e&&e.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),e&&j(n,e),t=[{key:"load",value:function(){var e;return(e=function(){var e;return function(e,t){var n,r,o,a={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]},i=Object.create(("function"==typeof Iterator?Iterator:Object).prototype),u=Object.defineProperty;return u(i,"next",{value:c(0)}),u(i,"throw",{value:c(1)}),u(i,"return",{value:c(2)}),"function"==typeof Symbol&&u(i,Symbol.iterator,{value:function(){return this}}),i;function c(u){return function(c){var l=[u,c];if(n)throw TypeError("Generator is already executing.");for(;i&&(i=0,l[0]&&(a=0)),a;)try{if(n=1,r&&(o=2&l[0]?r.return:l[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,l[1])).done)return o;switch(r=0,o&&(l=[2&l[0],o.value]),l[0]){case 0:case 1:o=l;break;case 4:return a.label++,{value:l[1],done:!1};case 5:a.label++,r=l[1],l=[0];continue;case 7:l=a.ops.pop(),a.trys.pop();continue;default:if(!(o=(o=a.trys).length>0&&o[o.length-1])&&(6===l[0]||2===l[0])){a=0;continue}if(3===l[0]&&(!o||l[1]>o[0]&&l[1]<o[3])){a.label=l[1];break}if(6===l[0]&&a.label<o[1]){a.label=o[1],o=l;break}if(o&&a.label<o[2]){a.label=o[2],a.ops.push(l);break}o[2]&&a.ops.pop(),a.trys.pop();continue}l=t.call(e,a)}catch(e){l=[6,e],r=0}finally{n=o=0}if(5&l[0])throw l[1];return{value:l[0]?l[1]:void 0,done:!0}}}}(this,function(t){return e=this,e.flowEngine.registerModels(_),e.router.add("idp-oauth.interaction",{path:"/idp-oauth/interaction/:uid",Component:C,skipAuthCheck:!0}),e.router.add("idp-oauth.device",{path:"/idpOAuth/device",Component:m,skipAuthCheck:!0}),e.router.add("idp-oauth.error",{path:"/idp-oauth/error",Component:v,skipAuthCheck:!0}),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,o){var a=e.apply(t,n);function i(e){T(a,r,o,i,u,"next",e)}function u(e){T(a,r,o,i,u,"throw",e)}i(void 0)})}).call(this)}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(n.prototype,t),n}(I(e.Plugin))}(),f}()});
|
package/dist/client/locale.d.ts
CHANGED
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
export declare function useT(): (str: string) => string;
|
|
9
|
+
export declare function useT(): (str: string, options?: Record<string, unknown>) => string;
|
|
10
10
|
export declare function tExpr(key: string): string;
|
package/dist/externalVersion.js
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
+
"@nocobase/client": "2.2.0-beta.8",
|
|
11
12
|
"antd": "5.24.2",
|
|
12
13
|
"react": "18.2.0",
|
|
13
14
|
"react-router-dom": "6.30.1",
|
|
14
|
-
"@nocobase/
|
|
15
|
-
"@nocobase/
|
|
16
|
-
"@nocobase/
|
|
17
|
-
"@nocobase/
|
|
18
|
-
"@nocobase/
|
|
19
|
-
"@nocobase/
|
|
20
|
-
"@nocobase/database": "2.2.0-beta.7"
|
|
15
|
+
"@nocobase/flow-engine": "2.2.0-beta.8",
|
|
16
|
+
"@nocobase/server": "2.2.0-beta.8",
|
|
17
|
+
"@nocobase/cache": "2.2.0-beta.8",
|
|
18
|
+
"@nocobase/plugin-auth": "2.2.0-beta.8",
|
|
19
|
+
"@nocobase/utils": "2.2.0-beta.8",
|
|
20
|
+
"@nocobase/database": "2.2.0-beta.8"
|
|
21
21
|
};
|
package/dist/locale/en-US.json
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"Application": "Application",
|
|
3
|
+
"Authorization is complete. You can return to the terminal.": "Authorization is complete. You can return to the terminal.",
|
|
4
|
+
"Back to home": "Back to home",
|
|
5
|
+
"Cancel": "Cancel",
|
|
6
|
+
"Confirm device": "Confirm device",
|
|
7
|
+
"Continue": "Continue",
|
|
8
|
+
"Device sign-in": "Device sign-in",
|
|
9
|
+
"Device sign-in cancelled": "Device sign-in cancelled",
|
|
10
|
+
"Device sign-in complete": "Device sign-in complete",
|
|
11
|
+
"Device sign-in failed": "Device sign-in failed",
|
|
12
|
+
"Enter the code shown in your terminal to continue signing in.": "Enter the code shown in your terminal to continue signing in.",
|
|
13
|
+
"Enter the device code.": "Enter the device code.",
|
|
14
|
+
"Failed to load device sign-in.": "Failed to load device sign-in.",
|
|
15
|
+
"Failed to submit device sign-in.": "Failed to submit device sign-in.",
|
|
16
|
+
"The device code has already been used.": "The device code has already been used.",
|
|
17
|
+
"The device code has expired.": "The device code has expired.",
|
|
18
|
+
"The device code was not found.": "The device code was not found.",
|
|
19
|
+
"The device sign-in request was cancelled.": "The device sign-in request was cancelled.",
|
|
20
|
+
"{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.": "{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal."
|
|
21
|
+
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"Application": "应用",
|
|
3
|
+
"Authorization is complete. You can return to the terminal.": "授权已完成。你可以返回终端。",
|
|
4
|
+
"Back to home": "返回首页",
|
|
5
|
+
"Cancel": "取消",
|
|
6
|
+
"Confirm device": "确认设备",
|
|
7
|
+
"Continue": "继续",
|
|
8
|
+
"Device sign-in": "设备登录",
|
|
9
|
+
"Device sign-in cancelled": "设备登录已取消",
|
|
10
|
+
"Device sign-in complete": "设备登录完成",
|
|
11
|
+
"Device sign-in failed": "设备登录失败",
|
|
12
|
+
"Enter the code shown in your terminal to continue signing in.": "输入终端中显示的代码以继续登录。",
|
|
13
|
+
"Enter the device code.": "请输入设备代码。",
|
|
14
|
+
"Failed to load device sign-in.": "加载设备登录失败。",
|
|
15
|
+
"Failed to submit device sign-in.": "提交设备登录失败。",
|
|
16
|
+
"The device code has already been used.": "设备代码已被使用。",
|
|
17
|
+
"The device code has expired.": "设备代码已过期。",
|
|
18
|
+
"The device code was not found.": "未找到设备代码。",
|
|
19
|
+
"The device sign-in request was cancelled.": "设备登录请求已取消。",
|
|
20
|
+
"{{clientName}} is requesting access. Confirm that this code matches the one shown in your terminal.": "{{clientName}} 正在请求访问。请确认此代码与终端中显示的代码一致。"
|
|
21
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-06-
|
|
1
|
+
{"name":"light-my-request","version":"6.6.0","description":"Fake HTTP injection library","main":"index.js","type":"commonjs","types":"types/index.d.ts","dependencies":{"cookie":"^1.0.1","process-warning":"^4.0.0","set-cookie-parser":"^2.6.0"},"devDependencies":{"@fastify/ajv-compiler":"^4.0.0","@fastify/pre-commit":"^2.1.0","@types/node":"^22.7.7","c8":"^10.1.2","end-of-stream":"^1.4.4","eslint":"^9.17.0","express":"^4.19.2","form-auto-content":"^3.2.1","form-data":"^4.0.0","formdata-node":"^6.0.3","multer":"^1.4.5-lts.1","neostandard":"^0.12.0","tinybench":"^3.0.0","tsd":"^0.31.0","undici":"^7.0.0"},"scripts":{"benchmark":"node benchmark/benchmark.js","coverage":"npm run unit -- --cov --coverage-report=html","lint":"eslint","lint:fix":"eslint --fix","test":"npm run lint && npm run test:unit && npm run test:typescript","test:typescript":"tsd","test:unit":"c8 --100 node --test"},"repository":{"type":"git","url":"git+https://github.com/fastify/light-my-request.git"},"keywords":["http","inject","fake","request","server"],"author":"Tomas Della Vedova - @delvedor (http://delved.org)","contributors":[{"name":"Matteo Collina","email":"hello@matteocollina.com"},{"name":"Manuel Spigolon","email":"behemoth89@gmail.com"},{"name":"Aras Abbasi","email":"aras.abbasi@gmail.com"},{"name":"Frazer Smith","email":"frazer.dev@icloud.com","url":"https://github.com/fdawgs"}],"license":"BSD-3-Clause","bugs":{"url":"https://github.com/fastify/light-my-request/issues"},"homepage":"https://github.com/fastify/light-my-request#readme","funding":[{"type":"github","url":"https://github.com/sponsors/fastify"},{"type":"opencollective","url":"https://opencollective.com/fastify"}],"_lastModified":"2026-06-29T01:53:47.387Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-06-
|
|
1
|
+
{"name":"ms","version":"2.1.3","description":"Tiny millisecond conversion utility","repository":"vercel/ms","main":"./index","files":["index.js"],"scripts":{"precommit":"lint-staged","lint":"eslint lib/* bin/*","test":"mocha tests.js"},"eslintConfig":{"extends":"eslint:recommended","env":{"node":true,"es6":true}},"lint-staged":{"*.js":["npm run lint","prettier --single-quote --write","git add"]},"license":"MIT","devDependencies":{"eslint":"4.18.2","expect.js":"0.3.1","husky":"0.14.3","lint-staged":"5.0.0","mocha":"4.0.1","prettier":"2.0.5"},"_lastModified":"2026-06-29T01:53:47.435Z"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import type { IdpOauthService } from './service';
|
|
10
|
+
type DeviceVerificationAction = 'show' | 'approve' | 'cancel';
|
|
11
|
+
type DeviceVerificationContext = {
|
|
12
|
+
method: string;
|
|
13
|
+
path: string;
|
|
14
|
+
query?: Record<string, unknown>;
|
|
15
|
+
request: {
|
|
16
|
+
body?: unknown;
|
|
17
|
+
};
|
|
18
|
+
status?: number;
|
|
19
|
+
body?: unknown;
|
|
20
|
+
withoutDataWrapping?: boolean;
|
|
21
|
+
throw: (...args: unknown[]) => never;
|
|
22
|
+
};
|
|
23
|
+
export declare function getDeviceVerificationAction(pathname: string, apiBasePath: string): DeviceVerificationAction | null;
|
|
24
|
+
export declare function isProviderDeviceVerificationPage(pathname: string, apiBasePath: string): boolean;
|
|
25
|
+
export declare function handleDeviceVerificationRequest(ctx: DeviceVerificationContext, service: IdpOauthService, apiBasePath: string): Promise<boolean>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var device_verification_exports = {};
|
|
28
|
+
__export(device_verification_exports, {
|
|
29
|
+
getDeviceVerificationAction: () => getDeviceVerificationAction,
|
|
30
|
+
handleDeviceVerificationRequest: () => handleDeviceVerificationRequest,
|
|
31
|
+
isProviderDeviceVerificationPage: () => isProviderDeviceVerificationPage
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(device_verification_exports);
|
|
34
|
+
var import_utils = require("./utils");
|
|
35
|
+
const OIDC_SCOPES = /* @__PURE__ */ new Set(["openid", "offline_access", "profile", "email"]);
|
|
36
|
+
function epochTime(date = Date.now()) {
|
|
37
|
+
return Math.floor(date / 1e3);
|
|
38
|
+
}
|
|
39
|
+
function normalizeUserCode(input) {
|
|
40
|
+
return String(input || "").replace(/[a-z]/g, (char) => char.toUpperCase()).replace(/\W/g, "");
|
|
41
|
+
}
|
|
42
|
+
function formatUserCode(input) {
|
|
43
|
+
var _a;
|
|
44
|
+
const userCode = normalizeUserCode(input);
|
|
45
|
+
return ((_a = userCode.match(/.{1,4}/g)) == null ? void 0 : _a.join("-")) || "";
|
|
46
|
+
}
|
|
47
|
+
function splitScopes(value) {
|
|
48
|
+
return typeof value === "string" ? value.split(/\s+/).filter(Boolean) : [];
|
|
49
|
+
}
|
|
50
|
+
function getStringArray(value) {
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
return value.filter((item) => typeof item === "string" && !!item);
|
|
53
|
+
}
|
|
54
|
+
return typeof value === "string" && value ? [value] : [];
|
|
55
|
+
}
|
|
56
|
+
function isRecordLike(value) {
|
|
57
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
58
|
+
}
|
|
59
|
+
function getUserCode(ctx) {
|
|
60
|
+
var _a;
|
|
61
|
+
const body = isRecordLike(ctx.request.body) ? ctx.request.body : void 0;
|
|
62
|
+
return normalizeUserCode((body == null ? void 0 : body.user_code) || ((_a = ctx.query) == null ? void 0 : _a.user_code));
|
|
63
|
+
}
|
|
64
|
+
function getDeviceVerificationAction(pathname, apiBasePath) {
|
|
65
|
+
const basePath = `${apiBasePath}/idpOAuth/device/verification`;
|
|
66
|
+
if (pathname === basePath) {
|
|
67
|
+
return "show";
|
|
68
|
+
}
|
|
69
|
+
if (pathname === `${basePath}:approve`) {
|
|
70
|
+
return "approve";
|
|
71
|
+
}
|
|
72
|
+
if (pathname === `${basePath}:cancel`) {
|
|
73
|
+
return "cancel";
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
function isProviderDeviceVerificationPage(pathname, apiBasePath) {
|
|
78
|
+
const devicePath = `${apiBasePath}/idpOAuth/device`;
|
|
79
|
+
if (pathname === devicePath) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (!pathname.startsWith(`${devicePath}/`)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
return !pathname.startsWith(`${devicePath}/auth`) && !pathname.startsWith(`${devicePath}/verification`);
|
|
86
|
+
}
|
|
87
|
+
async function findDeviceCode(provider, userCode) {
|
|
88
|
+
return provider.DeviceCode.findByUserCode(userCode, {
|
|
89
|
+
ignoreExpiration: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async function getDeviceClient(provider, code) {
|
|
93
|
+
if (!code.clientId) {
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
return provider.Client.find(code.clientId);
|
|
97
|
+
}
|
|
98
|
+
function getClientName(client) {
|
|
99
|
+
return (client == null ? void 0 : client.clientName) || (client == null ? void 0 : client.clientId) || "Application";
|
|
100
|
+
}
|
|
101
|
+
async function buildDeviceState(ctx, provider, user) {
|
|
102
|
+
const userCode = getUserCode(ctx);
|
|
103
|
+
const displayUserCode = formatUserCode(userCode);
|
|
104
|
+
if (!userCode) {
|
|
105
|
+
return {
|
|
106
|
+
status: "missing_code"
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const code = await findDeviceCode(provider, userCode);
|
|
110
|
+
if (!code) {
|
|
111
|
+
return {
|
|
112
|
+
status: "not_found",
|
|
113
|
+
userCode: displayUserCode
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const client = await getDeviceClient(provider, code);
|
|
117
|
+
const baseState = {
|
|
118
|
+
userCode: displayUserCode,
|
|
119
|
+
clientName: getClientName(client)
|
|
120
|
+
};
|
|
121
|
+
if (code.isExpired) {
|
|
122
|
+
return {
|
|
123
|
+
...baseState,
|
|
124
|
+
status: "expired"
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (code.error) {
|
|
128
|
+
return {
|
|
129
|
+
...baseState,
|
|
130
|
+
status: "cancelled"
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (code.accountId) {
|
|
134
|
+
return {
|
|
135
|
+
...baseState,
|
|
136
|
+
status: "complete"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (code.inFlight || code.consumed) {
|
|
140
|
+
return {
|
|
141
|
+
...baseState,
|
|
142
|
+
status: "already_used"
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
if (!user) {
|
|
146
|
+
return {
|
|
147
|
+
...baseState,
|
|
148
|
+
status: "login"
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
...baseState,
|
|
153
|
+
status: "pending"
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function getRequestedResources(params) {
|
|
157
|
+
return getStringArray(params.resource);
|
|
158
|
+
}
|
|
159
|
+
function splitRequestedScopes(params) {
|
|
160
|
+
const requestedScopes = splitScopes(params.scope);
|
|
161
|
+
const oidcScopes = requestedScopes.filter((scope) => OIDC_SCOPES.has(scope));
|
|
162
|
+
const resourceScopes = requestedScopes.filter((scope) => !OIDC_SCOPES.has(scope));
|
|
163
|
+
return {
|
|
164
|
+
requestedScopes,
|
|
165
|
+
oidcScopes,
|
|
166
|
+
resourceScopes
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async function approveDeviceCode(ctx, provider, user) {
|
|
170
|
+
if (!(user == null ? void 0 : user.id)) {
|
|
171
|
+
ctx.throw(401, "Authentication required");
|
|
172
|
+
}
|
|
173
|
+
const userCode = getUserCode(ctx);
|
|
174
|
+
const displayUserCode = formatUserCode(userCode);
|
|
175
|
+
const code = userCode ? await findDeviceCode(provider, userCode) : void 0;
|
|
176
|
+
if (!code || code.isExpired || code.error || code.accountId || code.inFlight || code.consumed) {
|
|
177
|
+
return buildDeviceState(ctx, provider, user);
|
|
178
|
+
}
|
|
179
|
+
const clientId = code.clientId;
|
|
180
|
+
const params = code.params || {};
|
|
181
|
+
const { requestedScopes, oidcScopes, resourceScopes } = splitRequestedScopes(params);
|
|
182
|
+
const resources = getRequestedResources(params);
|
|
183
|
+
const grant = new provider.Grant({
|
|
184
|
+
accountId: String(user.id),
|
|
185
|
+
clientId
|
|
186
|
+
});
|
|
187
|
+
if (oidcScopes.length) {
|
|
188
|
+
grant.addOIDCScope(oidcScopes.join(" "));
|
|
189
|
+
}
|
|
190
|
+
if (resourceScopes.length) {
|
|
191
|
+
resources.forEach((resource) => grant.addResourceScope(resource, resourceScopes.join(" ")));
|
|
192
|
+
}
|
|
193
|
+
Object.assign(code, {
|
|
194
|
+
accountId: String(user.id),
|
|
195
|
+
authTime: epochTime(),
|
|
196
|
+
grantId: await grant.save(),
|
|
197
|
+
resource: resources.length > 1 ? resources : resources[0],
|
|
198
|
+
scope: requestedScopes.join(" ")
|
|
199
|
+
});
|
|
200
|
+
if (!resources.length) {
|
|
201
|
+
delete code.resource;
|
|
202
|
+
}
|
|
203
|
+
await code.save();
|
|
204
|
+
return {
|
|
205
|
+
status: "complete",
|
|
206
|
+
userCode: displayUserCode,
|
|
207
|
+
clientName: getClientName(await getDeviceClient(provider, code))
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
async function cancelDeviceCode(ctx, provider) {
|
|
211
|
+
const userCode = getUserCode(ctx);
|
|
212
|
+
const displayUserCode = formatUserCode(userCode);
|
|
213
|
+
const code = userCode ? await findDeviceCode(provider, userCode) : void 0;
|
|
214
|
+
if (!code || code.isExpired || code.error || code.accountId || code.inFlight || code.consumed) {
|
|
215
|
+
return buildDeviceState(ctx, provider);
|
|
216
|
+
}
|
|
217
|
+
Object.assign(code, {
|
|
218
|
+
error: "access_denied",
|
|
219
|
+
errorDescription: "End-User aborted interaction"
|
|
220
|
+
});
|
|
221
|
+
await code.save();
|
|
222
|
+
return {
|
|
223
|
+
status: "cancelled",
|
|
224
|
+
userCode: displayUserCode,
|
|
225
|
+
clientName: getClientName(await getDeviceClient(provider, code))
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
async function handleDeviceVerificationRequest(ctx, service, apiBasePath) {
|
|
229
|
+
const action = getDeviceVerificationAction(ctx.path, apiBasePath);
|
|
230
|
+
if (!action) {
|
|
231
|
+
return false;
|
|
232
|
+
}
|
|
233
|
+
if (action === "show" && ctx.method !== "GET" || action !== "show" && ctx.method !== "POST") {
|
|
234
|
+
ctx.throw(405);
|
|
235
|
+
}
|
|
236
|
+
ctx.withoutDataWrapping = true;
|
|
237
|
+
const provider = await service.ensureProviderForContext(ctx);
|
|
238
|
+
const user = await (0, import_utils.resolveCurrentUser)(ctx, service);
|
|
239
|
+
const body = await service.runWithProviderContext(ctx, async () => {
|
|
240
|
+
if (action === "approve") {
|
|
241
|
+
return approveDeviceCode(ctx, provider, user);
|
|
242
|
+
}
|
|
243
|
+
if (action === "cancel") {
|
|
244
|
+
return cancelDeviceCode(ctx, provider);
|
|
245
|
+
}
|
|
246
|
+
return buildDeviceState(ctx, provider, user);
|
|
247
|
+
});
|
|
248
|
+
ctx.body = body;
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
252
|
+
0 && (module.exports = {
|
|
253
|
+
getDeviceVerificationAction,
|
|
254
|
+
handleDeviceVerificationRequest,
|
|
255
|
+
isProviderDeviceVerificationPage
|
|
256
|
+
});
|
|
@@ -50,6 +50,24 @@ function shouldSkipConsent(clientId) {
|
|
|
50
50
|
function getClientId(details) {
|
|
51
51
|
return String(details.params.client_id || "");
|
|
52
52
|
}
|
|
53
|
+
function isInteractionSessionNotFound(error) {
|
|
54
|
+
return error instanceof Error && error.name === "SessionNotFound" && error.error === "invalid_request";
|
|
55
|
+
}
|
|
56
|
+
async function getInteractionDetails(ctx, provider) {
|
|
57
|
+
try {
|
|
58
|
+
return await provider.interactionDetails(ctx.req, ctx.res);
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (!isInteractionSessionNotFound(error)) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
ctx.status = 400;
|
|
64
|
+
ctx.body = {
|
|
65
|
+
error: "invalid_request",
|
|
66
|
+
error_description: "The authorization request has expired or is no longer available."
|
|
67
|
+
};
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
53
71
|
async function getInteractionRedirect(ctx, provider, service, result, mergeWithLastSubmission) {
|
|
54
72
|
const redirectTo = await provider.interactionResult(ctx.req, ctx.res, result, {
|
|
55
73
|
mergeWithLastSubmission
|
|
@@ -130,7 +148,10 @@ async function completeConsent(ctx, provider, service, details, accountId) {
|
|
|
130
148
|
}
|
|
131
149
|
async function handleInteractionGet(ctx, provider, user, service) {
|
|
132
150
|
var _a;
|
|
133
|
-
const details = await
|
|
151
|
+
const details = await getInteractionDetails(ctx, provider);
|
|
152
|
+
if (!details) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
134
155
|
const interactionUser = user || await service.resolveInteractionSessionUser((_a = details.session) == null ? void 0 : _a.accountId);
|
|
135
156
|
if (details.prompt.name === "login") {
|
|
136
157
|
if (!interactionUser) {
|
|
@@ -165,7 +186,10 @@ async function handleInteractionGet(ctx, provider, user, service) {
|
|
|
165
186
|
}
|
|
166
187
|
async function handleInteractionPost(ctx, provider, user, service) {
|
|
167
188
|
var _a, _b;
|
|
168
|
-
const details = await
|
|
189
|
+
const details = await getInteractionDetails(ctx, provider);
|
|
190
|
+
if (!details) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
169
193
|
const interactionUser = user || await service.resolveInteractionSessionUser((_a = details.session) == null ? void 0 : _a.accountId);
|
|
170
194
|
if ((_b = ctx.request.body) == null ? void 0 : _b.cancel) {
|
|
171
195
|
ctx.body = {
|
package/dist/server/plugin.js
CHANGED
|
@@ -31,6 +31,7 @@ __export(plugin_exports, {
|
|
|
31
31
|
});
|
|
32
32
|
module.exports = __toCommonJS(plugin_exports);
|
|
33
33
|
var import_server = require("@nocobase/server");
|
|
34
|
+
var import_device_verification = require("./device-verification");
|
|
34
35
|
var import_interaction = require("./interaction");
|
|
35
36
|
var import_paths = require("./paths");
|
|
36
37
|
var import_provider_dispatch = require("./provider-dispatch");
|
|
@@ -71,6 +72,17 @@ class PluginIdpOauthServer extends import_server.Plugin {
|
|
|
71
72
|
await next();
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
75
|
+
if (await (0, import_device_verification.handleDeviceVerificationRequest)(ctx, this.service, paths.apiBasePath)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if ((0, import_device_verification.isProviderDeviceVerificationPage)(ctx.path, paths.apiBasePath)) {
|
|
79
|
+
ctx.withoutDataWrapping = true;
|
|
80
|
+
ctx.status = 404;
|
|
81
|
+
ctx.body = {
|
|
82
|
+
error: "not_found"
|
|
83
|
+
};
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
74
86
|
if (paths.isProviderPath(ctx.path)) {
|
|
75
87
|
await (0, import_provider_dispatch.dispatchCurrentRequestToProvider)(ctx, this.service, paths.apiBasePath);
|
|
76
88
|
return;
|
|
@@ -44,6 +44,7 @@ module.exports = __toCommonJS(provider_dispatch_exports);
|
|
|
44
44
|
var import_light_my_request = __toESM(require("light-my-request"));
|
|
45
45
|
var import_paths = require("./paths");
|
|
46
46
|
const LOOPBACK_REDIRECT_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1", "[::1]"]);
|
|
47
|
+
const DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
47
48
|
function getRequestBody(ctx) {
|
|
48
49
|
const body = ctx.request.body;
|
|
49
50
|
if (typeof body === "string") {
|
|
@@ -77,7 +78,12 @@ function assertRegistrationRedirectUris(ctx, pathname) {
|
|
|
77
78
|
};
|
|
78
79
|
return false;
|
|
79
80
|
}
|
|
81
|
+
const grantTypes = Array.isArray(body == null ? void 0 : body.grant_types) ? body.grant_types.filter((grantType) => typeof grantType === "string") : [];
|
|
82
|
+
const isDeviceCodeOnlyClient = grantTypes.includes(DEVICE_CODE_GRANT_TYPE) && !grantTypes.includes("authorization_code");
|
|
80
83
|
const redirectUris = body == null ? void 0 : body.redirect_uris;
|
|
84
|
+
if (isDeviceCodeOnlyClient && (redirectUris === void 0 || Array.isArray(redirectUris) && !redirectUris.length)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
81
87
|
if (!Array.isArray(redirectUris) || !redirectUris.length || !redirectUris.every((uri) => typeof uri === "string" && isLoopbackRedirectUri(uri))) {
|
|
82
88
|
ctx.status = 400;
|
|
83
89
|
ctx.body = {
|
|
@@ -152,12 +158,28 @@ function rewriteProviderUrl(ctx, service, value) {
|
|
|
152
158
|
function rewriteProviderLocationHeader(ctx, service, location) {
|
|
153
159
|
return rewriteProviderUrl(ctx, service, location);
|
|
154
160
|
}
|
|
161
|
+
function rewriteDeviceVerificationUrl(ctx, service, value) {
|
|
162
|
+
const { appName, origin, issuerPath } = service.getProviderContext(ctx);
|
|
163
|
+
const publicOriginUrl = new URL(origin);
|
|
164
|
+
const publicDevicePath = service.getFrontendDevicePath(appName, issuerPath);
|
|
165
|
+
try {
|
|
166
|
+
const url = value.startsWith("/") ? new URL(value, origin) : new URL(value);
|
|
167
|
+
url.protocol = publicOriginUrl.protocol;
|
|
168
|
+
url.host = publicOriginUrl.host;
|
|
169
|
+
url.pathname = publicDevicePath;
|
|
170
|
+
return url.toString();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
155
175
|
function getFrontendInteractionCookiePath(originalPath) {
|
|
156
|
-
const
|
|
157
|
-
|
|
176
|
+
const segments = originalPath.split("/").filter(Boolean);
|
|
177
|
+
const interactionIndex = segments.lastIndexOf("idp-oauth");
|
|
178
|
+
if (interactionIndex < 0 || segments[interactionIndex + 1] !== "interaction" || !segments[interactionIndex + 2] || segments.length !== interactionIndex + 3) {
|
|
158
179
|
return void 0;
|
|
159
180
|
}
|
|
160
|
-
const [
|
|
181
|
+
const appName = segments[interactionIndex - 2] === "apps" ? segments[interactionIndex - 1] : void 0;
|
|
182
|
+
const uid = segments[interactionIndex + 2];
|
|
161
183
|
return { appName, uid };
|
|
162
184
|
}
|
|
163
185
|
function rewriteProviderSetCookieHeader(ctx, service, cookie) {
|
|
@@ -188,6 +210,7 @@ function rewriteProviderJsonBody(ctx, service, body) {
|
|
|
188
210
|
"/idpOAuth/authorize",
|
|
189
211
|
"/idpOAuth/token",
|
|
190
212
|
"/idpOAuth/register",
|
|
213
|
+
"/idpOAuth/device/auth",
|
|
191
214
|
"/idpOAuth/revoke",
|
|
192
215
|
"/idpOAuth/jwks",
|
|
193
216
|
"/idpOAuth/me",
|
|
@@ -198,6 +221,7 @@ function rewriteProviderJsonBody(ctx, service, body) {
|
|
|
198
221
|
"authorization_endpoint",
|
|
199
222
|
"token_endpoint",
|
|
200
223
|
"registration_endpoint",
|
|
224
|
+
"device_authorization_endpoint",
|
|
201
225
|
"revocation_endpoint",
|
|
202
226
|
"jwks_uri",
|
|
203
227
|
"userinfo_endpoint",
|
|
@@ -216,8 +240,23 @@ function rewriteProviderJsonBody(ctx, service, body) {
|
|
|
216
240
|
const clientId = body.client_id || registrationClientUri.pathname.split("/").pop();
|
|
217
241
|
body.registration_client_uri = `${issuer}/idpOAuth/register/${clientId}`;
|
|
218
242
|
}
|
|
243
|
+
if (typeof body.verification_uri === "string") {
|
|
244
|
+
body.verification_uri = rewriteDeviceVerificationUrl(ctx, service, body.verification_uri);
|
|
245
|
+
}
|
|
246
|
+
if (typeof body.verification_uri_complete === "string") {
|
|
247
|
+
body.verification_uri_complete = rewriteDeviceVerificationUrl(ctx, service, body.verification_uri_complete);
|
|
248
|
+
}
|
|
219
249
|
return body;
|
|
220
250
|
}
|
|
251
|
+
function rewriteProviderHtmlBody(ctx, service, html) {
|
|
252
|
+
return html.replace(/\b(action|href)=(["'])(.*?)\2/g, (match, attribute, quote, value) => {
|
|
253
|
+
const rewritten = rewriteProviderUrl(ctx, service, value);
|
|
254
|
+
if (rewritten === value) {
|
|
255
|
+
return match;
|
|
256
|
+
}
|
|
257
|
+
return `${attribute}=${quote}${rewritten}${quote}`;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
221
260
|
function rewriteProviderResponseHeaders(ctx, service, headers) {
|
|
222
261
|
for (const [name, value] of Object.entries(headers)) {
|
|
223
262
|
if (value === void 0) {
|
|
@@ -239,6 +278,27 @@ function rewriteProviderResponseHeaders(ctx, service, headers) {
|
|
|
239
278
|
ctx.set(name, Array.isArray(value) ? value.map(String) : String(value));
|
|
240
279
|
}
|
|
241
280
|
}
|
|
281
|
+
function decodeProviderPayload(payload) {
|
|
282
|
+
if (typeof payload === "string") {
|
|
283
|
+
return payload;
|
|
284
|
+
}
|
|
285
|
+
if (Buffer.isBuffer(payload)) {
|
|
286
|
+
return payload.toString("utf8");
|
|
287
|
+
}
|
|
288
|
+
if (payload instanceof Uint8Array) {
|
|
289
|
+
return Buffer.from(payload).toString("utf8");
|
|
290
|
+
}
|
|
291
|
+
if (payload && typeof payload === "object" && payload.type === "Buffer" && Array.isArray(payload.data)) {
|
|
292
|
+
return Buffer.from(payload.data).toString("utf8");
|
|
293
|
+
}
|
|
294
|
+
return String(payload ?? "");
|
|
295
|
+
}
|
|
296
|
+
function resolveProviderPayloadBody(payload, payloadText) {
|
|
297
|
+
if (typeof payload === "string" || Buffer.isBuffer(payload) || payload instanceof Uint8Array) {
|
|
298
|
+
return payload.length ? payload : void 0;
|
|
299
|
+
}
|
|
300
|
+
return payloadText || void 0;
|
|
301
|
+
}
|
|
242
302
|
async function dispatchToProvider(ctx, provider, pathname, service) {
|
|
243
303
|
var _a, _b, _c, _d, _e, _f;
|
|
244
304
|
ctx.withoutDataWrapping = true;
|
|
@@ -261,8 +321,9 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
|
|
|
261
321
|
});
|
|
262
322
|
ctx.status = response.statusCode;
|
|
263
323
|
rewriteProviderResponseHeaders(ctx, service, response.headers);
|
|
324
|
+
const responseHeaders = response.headers;
|
|
264
325
|
const payload = response.rawPayload;
|
|
265
|
-
const contentType = String(
|
|
326
|
+
const contentType = String(responseHeaders["content-type"] || responseHeaders["Content-Type"] || "").toLowerCase();
|
|
266
327
|
(_d = (_c = ctx.logger) == null ? void 0 : _c.debug) == null ? void 0 : _d.call(_c, "idp-oauth provider response", {
|
|
267
328
|
method: ctx.method,
|
|
268
329
|
externalPath: ctx.path,
|
|
@@ -271,9 +332,11 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
|
|
|
271
332
|
contentType,
|
|
272
333
|
location: response.headers.location
|
|
273
334
|
});
|
|
274
|
-
|
|
335
|
+
const isDiscoveryResponse = ctx.path.endsWith("/.well-known/oauth-authorization-server") || ctx.path.endsWith("/.well-known/openid-configuration") || pathname.endsWith("/.well-known/oauth-authorization-server") || pathname.endsWith("/.well-known/openid-configuration");
|
|
336
|
+
const payloadText = decodeProviderPayload(payload);
|
|
337
|
+
if (payloadText && (isDiscoveryResponse || contentType.includes("application/json") || contentType.includes("+json"))) {
|
|
275
338
|
try {
|
|
276
|
-
const body = rewriteProviderJsonBody(ctx, service, JSON.parse(
|
|
339
|
+
const body = rewriteProviderJsonBody(ctx, service, JSON.parse(payloadText));
|
|
277
340
|
ctx.body = body;
|
|
278
341
|
return;
|
|
279
342
|
} catch (error) {
|
|
@@ -284,11 +347,15 @@ async function dispatchToProvider(ctx, provider, pathname, service) {
|
|
|
284
347
|
status: response.statusCode,
|
|
285
348
|
contentType,
|
|
286
349
|
error: error instanceof Error ? error.message : String(error),
|
|
287
|
-
payloadPreview:
|
|
350
|
+
payloadPreview: payloadText.slice(0, 500)
|
|
288
351
|
});
|
|
289
352
|
}
|
|
290
353
|
}
|
|
291
|
-
|
|
354
|
+
if (payloadText && contentType.includes("text/html")) {
|
|
355
|
+
ctx.body = rewriteProviderHtmlBody(ctx, service, payloadText);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
ctx.body = resolveProviderPayloadBody(payload, payloadText);
|
|
292
359
|
}
|
|
293
360
|
async function dispatchCurrentRequestToProvider(ctx, service, apiBasePath) {
|
|
294
361
|
const provider = await service.ensureProviderForContext(ctx);
|
package/dist/server/service.d.ts
CHANGED
|
@@ -42,6 +42,7 @@ export declare class IdpOauthService {
|
|
|
42
42
|
private getBridgeTokenCache;
|
|
43
43
|
getOrigin(ctx: any): string;
|
|
44
44
|
private getApiBasePath;
|
|
45
|
+
private getAppPublicPath;
|
|
45
46
|
private getRequestPath;
|
|
46
47
|
private getAppIssuerPath;
|
|
47
48
|
getIssuerPath(appName?: string, ctx?: any): string;
|
|
@@ -49,6 +50,7 @@ export declare class IdpOauthService {
|
|
|
49
50
|
private shouldUseSubAppPublicPrefix;
|
|
50
51
|
getFrontendInteractionPath(appName: string, uid: string, issuerPath?: string): string;
|
|
51
52
|
getFrontendErrorPath(appName: string, issuerPath?: string): string;
|
|
53
|
+
getFrontendDevicePath(appName: string, issuerPath?: string): string;
|
|
52
54
|
getProviderContext(ctx: any): ProviderContext;
|
|
53
55
|
getCurrentProviderContext(): ProviderContext;
|
|
54
56
|
runWithProviderContext<T>(ctx: any, callback: () => T): T;
|
package/dist/server/service.js
CHANGED
|
@@ -69,12 +69,121 @@ const envJwksKeys = ["IDP_OAUTH_JWKS", "OAUTH_JWKS"];
|
|
|
69
69
|
const MAX_CACHE_TTL_MS = 2147483647;
|
|
70
70
|
const DEFAULT_ACCESS_TOKEN_TTL_SECONDS = Math.floor((0, import_ms.default)(String(import_plugin_auth.defaultTokenPolicyConfig.tokenExpirationTime)) / 1e3);
|
|
71
71
|
const DEFAULT_SESSION_TTL_SECONDS = Math.floor((0, import_ms.default)(String(import_plugin_auth.defaultTokenPolicyConfig.sessionExpirationTime)) / 1e3);
|
|
72
|
+
const DEVICE_CODE_TTL_SECONDS = 10 * 60;
|
|
72
73
|
function policyMillisecondsToSeconds(value, fallback) {
|
|
73
74
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
74
75
|
return fallback;
|
|
75
76
|
}
|
|
76
77
|
return Math.max(1, Math.floor(value / 1e3));
|
|
77
78
|
}
|
|
79
|
+
function escapeHtmlText(value) {
|
|
80
|
+
return String(value ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
81
|
+
}
|
|
82
|
+
function renderDevicePage(options) {
|
|
83
|
+
return `<!doctype html>
|
|
84
|
+
<html lang="en">
|
|
85
|
+
<head>
|
|
86
|
+
<meta charset="utf-8">
|
|
87
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
88
|
+
<title>${escapeHtmlText(options.title)}</title>
|
|
89
|
+
<style>
|
|
90
|
+
* { box-sizing: border-box; }
|
|
91
|
+
body {
|
|
92
|
+
margin: 0;
|
|
93
|
+
min-height: 100vh;
|
|
94
|
+
display: grid;
|
|
95
|
+
place-items: center;
|
|
96
|
+
padding: 24px;
|
|
97
|
+
background: #f5f5f5;
|
|
98
|
+
color: rgba(0, 0, 0, 0.88);
|
|
99
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
100
|
+
}
|
|
101
|
+
main {
|
|
102
|
+
width: min(100%, 440px);
|
|
103
|
+
padding: 32px;
|
|
104
|
+
border: 1px solid #f0f0f0;
|
|
105
|
+
border-radius: 8px;
|
|
106
|
+
background: #fff;
|
|
107
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.08);
|
|
108
|
+
}
|
|
109
|
+
h1 { margin: 0 0 12px; font-size: 26px; line-height: 1.25; font-weight: 600; }
|
|
110
|
+
p { margin: 0 0 20px; color: rgba(0, 0, 0, 0.65); line-height: 1.7; }
|
|
111
|
+
form { display: grid; gap: 12px; }
|
|
112
|
+
input[type="text"] {
|
|
113
|
+
width: 100%;
|
|
114
|
+
height: 44px;
|
|
115
|
+
padding: 0 12px;
|
|
116
|
+
border: 1px solid #d9d9d9;
|
|
117
|
+
border-radius: 6px;
|
|
118
|
+
font-size: 18px;
|
|
119
|
+
text-align: center;
|
|
120
|
+
text-transform: uppercase;
|
|
121
|
+
letter-spacing: 0.08em;
|
|
122
|
+
}
|
|
123
|
+
button {
|
|
124
|
+
min-height: 40px;
|
|
125
|
+
border: 1px solid #1677ff;
|
|
126
|
+
border-radius: 6px;
|
|
127
|
+
background: #1677ff;
|
|
128
|
+
color: #fff;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
font-size: 14px;
|
|
131
|
+
font-weight: 500;
|
|
132
|
+
}
|
|
133
|
+
button[name="abort"] {
|
|
134
|
+
margin-top: 8px;
|
|
135
|
+
border: 0;
|
|
136
|
+
background: transparent;
|
|
137
|
+
color: rgba(0, 0, 0, 0.45);
|
|
138
|
+
}
|
|
139
|
+
code {
|
|
140
|
+
display: inline-block;
|
|
141
|
+
margin: 8px 0;
|
|
142
|
+
font-size: 28px;
|
|
143
|
+
letter-spacing: 0.08em;
|
|
144
|
+
color: rgba(0, 0, 0, 0.88);
|
|
145
|
+
}
|
|
146
|
+
.footer { margin-top: 20px; margin-bottom: 0; font-size: 13px; color: rgba(0, 0, 0, 0.45); }
|
|
147
|
+
</style>
|
|
148
|
+
</head>
|
|
149
|
+
<body>
|
|
150
|
+
<main>
|
|
151
|
+
<h1>${escapeHtmlText(options.heading)}</h1>
|
|
152
|
+
<p>${escapeHtmlText(options.description)}</p>
|
|
153
|
+
${options.form ?? ""}
|
|
154
|
+
${options.footer ? `<p class="footer">${escapeHtmlText(options.footer)}</p>` : ""}
|
|
155
|
+
</main>
|
|
156
|
+
</body>
|
|
157
|
+
</html>`;
|
|
158
|
+
}
|
|
159
|
+
async function renderDeviceCodeInput(ctx, form, out, error) {
|
|
160
|
+
const description = error || (out == null ? void 0 : out.error) ? "The code could not be verified. Check the code from your device and try again." : "Enter the code shown in your terminal to continue signing in.";
|
|
161
|
+
ctx.body = renderDevicePage({
|
|
162
|
+
title: "Device sign-in",
|
|
163
|
+
heading: "Device sign-in",
|
|
164
|
+
description,
|
|
165
|
+
form: `${form}<button type="submit" form="op.deviceInputForm">Continue</button>`
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
async function renderDeviceCodeConfirmation(ctx, form, client, _deviceInfo, userCode) {
|
|
169
|
+
const clientName = client.clientName || client.clientId || "Application";
|
|
170
|
+
ctx.body = renderDevicePage({
|
|
171
|
+
title: "Confirm device",
|
|
172
|
+
heading: "Confirm device",
|
|
173
|
+
description: `${clientName} is requesting access. Confirm that this code matches the one shown in your terminal.`,
|
|
174
|
+
form: `<p><code>${escapeHtmlText(
|
|
175
|
+
userCode
|
|
176
|
+
)}</code></p>${form}<button autofocus type="submit" form="op.deviceConfirmForm">Continue</button><button type="submit" form="op.deviceConfirmForm" value="yes" name="abort">Cancel</button>`
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
async function renderDeviceSuccess(ctx) {
|
|
180
|
+
ctx.body = renderDevicePage({
|
|
181
|
+
title: "Device sign-in complete",
|
|
182
|
+
heading: "Device sign-in complete",
|
|
183
|
+
description: "Authorization is complete. You can return to the terminal.",
|
|
184
|
+
footer: "This browser tab can be closed."
|
|
185
|
+
});
|
|
186
|
+
}
|
|
78
187
|
class IdpOauthService {
|
|
79
188
|
constructor(app, bridgeTokenCache) {
|
|
80
189
|
this.app = app;
|
|
@@ -105,6 +214,15 @@ class IdpOauthService {
|
|
|
105
214
|
getApiBasePath() {
|
|
106
215
|
return (0, import_utils2.normalizeBasePath)(process.env.API_BASE_PATH || "/api");
|
|
107
216
|
}
|
|
217
|
+
getAppPublicPath() {
|
|
218
|
+
const appPublicPath = (0, import_utils2.normalizeBasePath)(process.env.APP_PUBLIC_PATH || "");
|
|
219
|
+
if (appPublicPath !== "/") {
|
|
220
|
+
return appPublicPath;
|
|
221
|
+
}
|
|
222
|
+
const apiBasePath = this.getApiBasePath();
|
|
223
|
+
const inferredPublicPath = apiBasePath.endsWith("/api") ? (0, import_utils2.normalizeBasePath)(apiBasePath.slice(0, -4)) : "";
|
|
224
|
+
return inferredPublicPath === "/" ? "" : inferredPublicPath;
|
|
225
|
+
}
|
|
108
226
|
getRequestPath(ctx) {
|
|
109
227
|
var _a, _b;
|
|
110
228
|
if (typeof ((_a = ctx == null ? void 0 : ctx.req) == null ? void 0 : _a.originalUrl) === "string") {
|
|
@@ -154,16 +272,25 @@ class IdpOauthService {
|
|
|
154
272
|
return issuerPath !== this.getApiBasePath();
|
|
155
273
|
}
|
|
156
274
|
getFrontendInteractionPath(appName, uid, issuerPath = this.getIssuerPath(appName)) {
|
|
275
|
+
const appPublicPath = this.getAppPublicPath();
|
|
157
276
|
if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
|
|
158
|
-
return
|
|
277
|
+
return `${appPublicPath}/idp-oauth/interaction/${uid}`;
|
|
159
278
|
}
|
|
160
|
-
return
|
|
279
|
+
return `${appPublicPath}/apps/${appName}/idp-oauth/interaction/${uid}`;
|
|
161
280
|
}
|
|
162
281
|
getFrontendErrorPath(appName, issuerPath = this.getIssuerPath(appName)) {
|
|
282
|
+
const appPublicPath = this.getAppPublicPath();
|
|
283
|
+
if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
|
|
284
|
+
return `${appPublicPath}/idp-oauth/error`;
|
|
285
|
+
}
|
|
286
|
+
return `${appPublicPath}/apps/${appName}/idp-oauth/error`;
|
|
287
|
+
}
|
|
288
|
+
getFrontendDevicePath(appName, issuerPath = this.getIssuerPath(appName)) {
|
|
289
|
+
const appPublicPath = this.getAppPublicPath();
|
|
163
290
|
if (!this.shouldUseSubAppPublicPrefix(appName, issuerPath)) {
|
|
164
|
-
return
|
|
291
|
+
return `${appPublicPath}/idpOAuth/device`;
|
|
165
292
|
}
|
|
166
|
-
return
|
|
293
|
+
return `${appPublicPath}/apps/${appName}/idpOAuth/device`;
|
|
167
294
|
}
|
|
168
295
|
getProviderContext(ctx) {
|
|
169
296
|
var _a;
|
|
@@ -574,6 +701,8 @@ class IdpOauthService {
|
|
|
574
701
|
routes: {
|
|
575
702
|
authorization: "/idpOAuth/authorize",
|
|
576
703
|
token: "/idpOAuth/token",
|
|
704
|
+
code_verification: "/idpOAuth/device",
|
|
705
|
+
device_authorization: "/idpOAuth/device/auth",
|
|
577
706
|
jwks: "/idpOAuth/jwks",
|
|
578
707
|
registration: "/idpOAuth/register",
|
|
579
708
|
revocation: "/idpOAuth/revoke",
|
|
@@ -582,6 +711,12 @@ class IdpOauthService {
|
|
|
582
711
|
end_session: "/idpOAuth/end-session"
|
|
583
712
|
},
|
|
584
713
|
features: {
|
|
714
|
+
deviceFlow: {
|
|
715
|
+
enabled: true,
|
|
716
|
+
userCodeInputSource: renderDeviceCodeInput,
|
|
717
|
+
userCodeConfirmSource: renderDeviceCodeConfirmation,
|
|
718
|
+
successSource: renderDeviceSuccess
|
|
719
|
+
},
|
|
585
720
|
devInteractions: { enabled: false },
|
|
586
721
|
registration: { enabled: true },
|
|
587
722
|
revocation: { enabled: true },
|
|
@@ -619,6 +754,7 @@ class IdpOauthService {
|
|
|
619
754
|
ttl: {
|
|
620
755
|
AccessToken: accessTokenTtl,
|
|
621
756
|
AuthorizationCode: 60,
|
|
757
|
+
DeviceCode: DEVICE_CODE_TTL_SECONDS,
|
|
622
758
|
Grant: sessionTtl,
|
|
623
759
|
IdToken: 60 * 60,
|
|
624
760
|
RefreshToken: sessionTtl,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-idp-oauth",
|
|
3
|
-
"version": "2.2.0-beta.
|
|
3
|
+
"version": "2.2.0-beta.8",
|
|
4
4
|
"main": "dist/server/index.js",
|
|
5
5
|
"displayName": "IdP: OAuth",
|
|
6
6
|
"displayName.zh-CN": "IdP: OAuth",
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"keywords": [
|
|
23
23
|
"Authentication"
|
|
24
24
|
],
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "fa2502c1e9faf6d74b3f51b42dbc6546638d46af"
|
|
26
26
|
}
|