diff --git a/demos/jans-tarp/.gitignore b/demos/jans-tarp/.gitignore index 22b9f913967..5683ef3b5e6 100644 --- a/demos/jans-tarp/.gitignore +++ b/demos/jans-tarp/.gitignore @@ -1,4 +1,5 @@ node_modules dist release -package-lock.json \ No newline at end of file +package-lock.json +src/wasm \ No newline at end of file diff --git a/demos/jans-tarp/README.md b/demos/jans-tarp/README.md index d4a06130d05..3d337a1dbc3 100644 --- a/demos/jans-tarp/README.md +++ b/demos/jans-tarp/README.md @@ -2,9 +2,10 @@ ## Relying Party tool in form of a Browser Extension. -[Demo Video](https://www.loom.com/share/6bfe8c5556a94abea05467e3deead8a2?sid=b65c81d9-c1a1-475c-b89b-c105887d31ad) +[Demo Video](https://www.loom.com/share/b112b9c7214a4920812a2ebe9c36dbf5?sid=7a15d2e5-881e-4002-9b8c-902dd1d80cec) -This extension is for convenient testing of authentication flows on browser. +- This extension is for convenient testing of authentication flows on browser. +- [Cedarling](https://docs.jans.io/head/cedarling/cedarling-overview/) is an embeddable stateful Policy Decision Point, or "PDP". Cedarling is integrated with Jans Tarp to make authorization post-authentication. ## Supporting Browser @@ -18,9 +19,10 @@ This extension is for convenient testing of authentication flows on browser. ## Build 1. Change directory to the project directory (`/jans-tarp`). -2. Run `npm install`. -3. Run `npm run build`. It will create Chrome and Firefox build in `/jans-tarp/dist/chrome` and `/jans-tarp/dist/firefox` directories respectively. -4. To pack the build into a zip file run `npm run pack`. This command will pack Chrome and Firefox builds in zip files at `/jans-tarp/release`. +2. Download and extract Cedarling WASM bindings from https://github.com/JanssenProject/jans/releases/download/nightly/cedarling_wasm_{version}_pkg.tar.gz to `/jans-tarp/src/wasm`. +3. Run `npm install`. +4. Run `npm run build`. It will create Chrome and Firefox build in `/jans-tarp/dist/chrome` and `/jans-tarp/dist/firefox` directories respectively. +5. To pack the build into a zip file run `npm run pack`. This command will pack Chrome and Firefox builds in zip files at `/jans-tarp/release`. ## Releases diff --git a/demos/jans-tarp/package.json b/demos/jans-tarp/package.json index 392bcd3777a..e32fd55220e 100644 --- a/demos/jans-tarp/package.json +++ b/demos/jans-tarp/package.json @@ -7,6 +7,7 @@ "scripts": { "watch": "webpack --watch --progress --config webpack.dev.js", "build": "webpack --mode=production --progress --config webpack.prod.js", + "build-dev": "webpack --mode=development --progress --config webpack.dev.js", "pack": "node pack.js" }, "devDependencies": { @@ -38,6 +39,7 @@ "autoprefixer": "^10.4.7", "axios": "^1.4.0", "dayjs": "^1.11.10", + "json-edit-react": "^1.19.2", "jwt-decode": "^4.0.0", "moment": "^2.29.4", "postcss": "^8.4.14", @@ -47,6 +49,7 @@ "react-select": "^5.7.3", "react-spinner-overlay": "^0.1.33", "styled-components": "^6.1.0", - "uuid": "^9.0.0" + "uuid": "^9.0.0", + "wasm": "file:src/wasm" } } diff --git a/demos/jans-tarp/src/options/addCedarlingConfig.tsx b/demos/jans-tarp/src/options/addCedarlingConfig.tsx new file mode 100644 index 00000000000..bf63ecfb533 --- /dev/null +++ b/demos/jans-tarp/src/options/addCedarlingConfig.tsx @@ -0,0 +1,200 @@ +import * as React from 'react'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogContentText from '@mui/material/DialogContentText'; +import DialogTitle from '@mui/material/DialogTitle'; +import CircularProgress from "@mui/material/CircularProgress"; +import Stack from '@mui/material/Stack'; +import Alert from '@mui/material/Alert'; +import __wbg_init, { init, Cedarling } from "wasm"; +import { v4 as uuidv4 } from 'uuid'; +import Radio from '@mui/material/Radio'; +import RadioGroup from '@mui/material/RadioGroup'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import { JsonEditor } from 'json-edit-react'; +import axios from 'axios'; + +export default function AddCedarlingConfig({ isOpen, handleDialog, newData }) { + const [open, setOpen] = React.useState(isOpen); + const [bootstrap, setBootstrap] = React.useState(newData); + const [errorMessage, setErrorMessage] = React.useState("") + const [loading, setLoading] = React.useState(false); + const [inputSelection, setInputSelection] = React.useState("json"); + + const ADD_BOOTSTRAP_ERROR = 'Error in adding bootstrap. Check web console for logs.' + + React.useEffect(() => { + if (isOpen) { + handleOpen(); + } else { + handleClose(); + } + }, [isOpen]); + + React.useEffect(() => { + setBootstrap(newData) + }, [newData]); + + const handleClose = () => { + setInputSelection('json') + handleDialog(false) + setOpen(false); + }; + + const handleOpen = () => { + setErrorMessage(''); + setLoading(false); + handleDialog(true) + setOpen(true); + }; + + const validateBootstrap = async (e) => { + let bootstrap = e.target.value; + setErrorMessage(''); + if (inputSelection === 'url') { + let bootstrapUrl = e.target.value; + if (bootstrapUrl === '') { + setErrorMessage('URL is required.'); + return false; + } + const oidcConfigOptions = { + method: 'GET', + url: bootstrapUrl, + }; + const response = await axios(oidcConfigOptions); + bootstrap = response.data; + + } else if (inputSelection === 'json') { + bootstrap = e.target.value; + } + if (isEmpty(bootstrap) || Object.keys(bootstrap).length === 0) { + setErrorMessage('Empty authorization request not allowed.'); + return false; + } + isJsonValid(bootstrap); + }; + + const isJsonValid = async (bootstrap) => { + setErrorMessage(''); + try { + setBootstrap(JSON.parse(JSON.stringify(bootstrap))); + return true; + } catch (err) { + console.error(err) + setErrorMessage(`Invalid input: ${err}`); + return false; + } + }; + + const saveBootstrap = async () => { + try { + setLoading(true); + if (!isJsonValid(bootstrap)) { + return; + } + + await __wbg_init(); + let instance: Cedarling = await init(bootstrap); + + chrome.storage.local.get(["cedarlingConfig"], (result) => { + let bootstrapArr = [] + + let idObj = { id: uuidv4() }; + + bootstrapArr.push({ ...bootstrap, ...idObj }); + chrome.storage.local.set({ cedarlingConfig: bootstrapArr }); + handleClose(); + }); + } catch (err) { + console.error(err) + setErrorMessage(ADD_BOOTSTRAP_ERROR + err) + } + setLoading(false); + } + + const isEmpty = (value) => { + return (value == null || value.length === 0); + } + return ( + + { + event.preventDefault(); + }, + }} + className="form-container" + > + Add Cedarling Configuration + {loading ? ( +
+ +
+ ) : ( + "" + )} + + + Submit below details. + + + {(!!errorMessage || errorMessage !== '') ? + {errorMessage} : '' + } + + { setErrorMessage(''); setInputSelection("json"); }} color="success" />} label="JSON" /> + { setErrorMessage(''); setInputSelection("url") }} />} label="URL" /> + + {inputSelection === 'json' ? + + : ''} + {inputSelection === 'url' ? + { + validateBootstrap(e); + }} + /> : ''} + + + + + + +
+
+ ); +} \ No newline at end of file diff --git a/demos/jans-tarp/src/options/authFlowInputs.tsx b/demos/jans-tarp/src/options/authFlowInputs.tsx index 20c88d10840..72f80ce5f81 100644 --- a/demos/jans-tarp/src/options/authFlowInputs.tsx +++ b/demos/jans-tarp/src/options/authFlowInputs.tsx @@ -448,6 +448,7 @@ export default function AuthFlowInputs({ isOpen, handleDialog, client, notifyOnD )} /> + setDisplayToken(!displayToken)}/>} label="Display Access Token and ID Token after authentication" /> diff --git a/demos/jans-tarp/src/options/cedarling.tsx b/demos/jans-tarp/src/options/cedarling.tsx new file mode 100644 index 00000000000..c4d5d1991f8 --- /dev/null +++ b/demos/jans-tarp/src/options/cedarling.tsx @@ -0,0 +1,148 @@ +import * as React from 'react'; +import Table from '@mui/material/Table'; +import TableBody from '@mui/material/TableBody'; +import TableCell, { tableCellClasses } from '@mui/material/TableCell'; +import TableContainer from '@mui/material/TableContainer'; +import TableHead from '@mui/material/TableHead'; +import TableRow from '@mui/material/TableRow'; +import Edit from '@mui/icons-material/Edit'; +import { pink, green } from '@mui/material/colors'; +import Grid from '@mui/material/Grid'; +import { styled } from '@mui/material/styles'; +import Paper from '@mui/material/Paper'; +import AddIcon from '@mui/icons-material/Add'; +import Container from '@mui/material/Container'; +import Button from '@mui/material/Button'; +import Stack from '@mui/material/Stack'; +import AddCedarlingConfig from './addCedarlingConfig' +import IconButton from '@mui/material/IconButton'; +import Tooltip from '@mui/material/Tooltip'; +import DeleteForeverOutlinedIcon from '@mui/icons-material/DeleteForeverOutlined'; +import HelpDrawer from './helpDrawer' +import Alert from '@mui/material/Alert'; +import { JsonEditor } from 'json-edit-react' + +const StyledTableCell = styled(TableCell)(({ theme }) => ({ + [`&.${tableCellClasses.head}`]: { + backgroundColor: theme.palette.common.black, + color: theme.palette.common.white, + }, + [`&.${tableCellClasses.body}`]: { + fontSize: 14, + }, +})); + +function Row(props: { row: any, notifyOnDataChange }) { + const { row, notifyOnDataChange } = props; + const [open, setOpen] = React.useState(false); + + const handleDialog = (isOpen) => { + setOpen(isOpen); + notifyOnDataChange(); + }; + + async function resetBootstrap() { + chrome.storage.local.get(["cedarlingConfig"], (result) => { + let cedarlingConfigArr = [] + chrome.storage.local.set({ cedarlingConfig: cedarlingConfigArr }); + }); + notifyOnDataChange(); + } + + return ( + + + *': { borderBottom: 'unset' } }}> + + + + + + + + + + + + + + + + { + setOpen(true); + notifyOnDataChange(); + }} /> + + + + + + + ); +} + +export default function Cedarling({ data, notifyOnDataChange, isOidcClientRegistered }) { + const [modelOpen, setModelOpen] = React.useState(false); + const [drawerOpen, setDrawerOpen] = React.useState(false); + const [oidcClientRegistered, setOidcClientRegistered] = React.useState(false); + + + React.useEffect(() => { + setOidcClientRegistered(isOidcClientRegistered) + }, [isOidcClientRegistered]); + + const handleDialog = (isOpen) => { + setModelOpen(isOpen); + notifyOnDataChange(); + }; + + const handleDrawer = (isOpen) => { + setDrawerOpen(isOpen); + }; + + return ( + + {oidcClientRegistered ? + <> + + + + + {(data === undefined || data?.length == 0) ? + : ''} + + + + + + + Bootstrap Configuration + Action + + + + {(data === undefined || data?.length == 0) ? + No Records to show. : + data.map((row, index) => ()) + } + +
+
+
+ : + At least one OIDC client must be registered in Jans-TARP to add Cedarling configuration. + } +
+ ); +} \ No newline at end of file diff --git a/demos/jans-tarp/src/options/homePage.tsx b/demos/jans-tarp/src/options/homePage.tsx new file mode 100644 index 00000000000..804908777ee --- /dev/null +++ b/demos/jans-tarp/src/options/homePage.tsx @@ -0,0 +1,86 @@ +import * as React from 'react'; +import Container from '@mui/material/Container'; +import Tabs from '@mui/material/Tabs'; +import Tab from '@mui/material/Tab'; +import Box from '@mui/material/Box'; +import Password from '@mui/icons-material/Password'; +import LockPerson from '@mui/icons-material/LockPerson'; +import OIDCClients from './OIDCClients'; +import Cedarling from './cedarling'; +import Grid from '@mui/material/Grid'; +import Paper from '@mui/material/Paper'; +import { styled } from '@mui/material/styles'; + +interface TabPanelProps { + children?: React.ReactNode; + index: number; + value: number; +} + +function CustomTabPanel(props: TabPanelProps) { + const { children, value, index, ...other } = props; + + return ( + + ); +} + +function a11yProps(index: number) { + return { + id: `simple-tab-${index}`, + 'aria-controls': `simple-tabpanel-${index}`, + }; +} + +export default function HomePage({ data, notifyOnDataChange }) { + + const [value, setValue] = React.useState(0); + + const handleChange = (event: React.SyntheticEvent, newValue: number) => { + setValue(newValue); + }; + + return ( + + + + } /> + } /> + + + + + + + + + + + + + + ); +} \ No newline at end of file diff --git a/demos/jans-tarp/src/options/oidcClients.tsx b/demos/jans-tarp/src/options/oidcClients.tsx index d18ea9a298c..af33fea6a05 100644 --- a/demos/jans-tarp/src/options/oidcClients.tsx +++ b/demos/jans-tarp/src/options/oidcClients.tsx @@ -84,7 +84,6 @@ function Row(props: { row: ReturnType, notifyOnDataChange }) let clientArr = [] if (!!result.oidcClients) { clientArr = result.oidcClients; - chrome.storage.local.set({ oidcClients: clientArr.filter(obj => obj.clientId !== row.clientId) }); } }); @@ -93,7 +92,7 @@ function Row(props: { row: ReturnType, notifyOnDataChange }) return ( - + *': { borderBottom: 'unset' } }}> diff --git a/demos/jans-tarp/src/options/options.tsx b/demos/jans-tarp/src/options/options.tsx index cc76c137fc2..ff0e2288658 100644 --- a/demos/jans-tarp/src/options/options.tsx +++ b/demos/jans-tarp/src/options/options.tsx @@ -1,8 +1,9 @@ import React, { useState, useEffect } from 'react' import './options.css' import Header from './header' -import OIDCClients from './oidcClients' +import HomePage from './homePage' import UserDetails from './userDetails' +import { ILooseObject } from './ILooseObject' const Options = () => { @@ -15,17 +16,26 @@ const Options = () => { if (!isEmpty(oidcClientResults) && Object.keys(oidcClientResults).length !== 0) { - chrome.storage.local.get(["loginDetails"], (loginDetailsResult) => { + chrome.storage.local.get(["loginDetails"], async (loginDetailsResult) => { if (!isEmpty(loginDetailsResult) && Object.keys(loginDetailsResult).length !== 0) { setOptionType('loginPage'); setdata(loginDetailsResult); } else { - setOptionType('oidcClientPage'); - setdata(oidcClientResults); + let collectedData = {}; + setOptionType('homePage'); + collectedData = { ...data, ...oidcClientResults }; + + let cedarlingConfig: ILooseObject = await new Promise((resolve, reject) => { chrome.storage.local.get(["cedarlingConfig"], (result) => { resolve(result); }) }); + + if (!isEmpty(cedarlingConfig) && Object.keys(cedarlingConfig).length !== 0) { + collectedData = { ...collectedData, ...cedarlingConfig }; + } + + setdata(collectedData); } }); } else { - setOptionType('oidcClientPage'); + setOptionType('homePage'); setdata({}); } setDataChanged(false); @@ -42,9 +52,9 @@ const Options = () => { function renderPage({ optionType, data }) { switch (optionType) { - case 'oidcClientPage': - return case 'loginPage': diff --git a/demos/jans-tarp/src/options/registerClient.tsx b/demos/jans-tarp/src/options/registerClient.tsx index 79a4770e51b..d908e821a2b 100644 --- a/demos/jans-tarp/src/options/registerClient.tsx +++ b/demos/jans-tarp/src/options/registerClient.tsx @@ -54,7 +54,7 @@ export default function RegisterClient({ isOpen, handleDialog }) { }; const validateIssuer = async (e) => { - + setIssuerError(''); let issuer = e.target.value; if (issuer.length === 0) { @@ -221,7 +221,7 @@ export default function RegisterClient({ isOpen, handleDialog }) { event.preventDefault(); }, }} - className="form-container" + className="form-container" > Register OIDC Client {loading ? ( diff --git a/demos/jans-tarp/src/options/userDetails.tsx b/demos/jans-tarp/src/options/userDetails.tsx index 3aea22ce430..351f4f842ef 100644 --- a/demos/jans-tarp/src/options/userDetails.tsx +++ b/demos/jans-tarp/src/options/userDetails.tsx @@ -3,12 +3,113 @@ import { v4 as uuidv4 } from 'uuid'; import './options.css' import './alerts.css'; import { WindmillSpinner } from 'react-spinner-overlay' +import { JsonEditor } from 'json-edit-react' +import TextField from '@mui/material/TextField'; +import InputLabel from '@mui/material/InputLabel'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import Checkbox from '@mui/material/Checkbox'; +import Button from '@mui/material/Button'; +import Accordion from '@mui/material/Accordion'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import Typography from '@mui/material/Typography'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; -const UserDetails = ({data, notifyOnDataChange}) => { +import __wbg_init, { init, Cedarling, AuthorizeResult } from "wasm"; + +const UserDetails = ({ data, notifyOnDataChange }) => { const [loading, setLoading] = useState(false); const [showMoreIdToken, setShowMoreIdToken] = useState(false); const [showMoreAT, setShowMoreAT] = useState(false); const [showMoreUI, setShowMoreUI] = useState(false); + const [context, setContext] = React.useState({}); + const [action, setAction] = React.useState(""); + const [accessToken, setAccessToken] = React.useState(false); + const [userInfoToken, setUserInfoToken] = React.useState(false); + const [idToken, setIdToken] = React.useState(false); + const [resource, setResource] = React.useState({}); + const [cedarlingBootstrapPresent, setCedarlingBootstrapPresent] = React.useState(false); + const [errorMessage, setErrorMessage] = React.useState("") + const [authzResult, setAuthzResult] = React.useState("") + const [authzLogs, setAuthzLogs] = React.useState("") + + + React.useEffect(() => { + chrome.storage.local.get(["authzRequest"], (authzRequest) => { + if (!isEmpty(authzRequest) && Object.keys(authzRequest).length !== 0) { + setContext(authzRequest.authzRequest.context); + setAction(authzRequest.authzRequest.action); + setResource(authzRequest.authzRequest.resource); + } + }); + chrome.storage.local.get(["cedarlingConfig"], async (cedarlingConfig) => { + setCedarlingBootstrapPresent(false); + if (Object.keys(cedarlingConfig).length !== 0 && !isEmpty(cedarlingConfig?.cedarlingConfig)) { + setCedarlingBootstrapPresent(true); + } + }); + }, []) + + const triggerCedarlingAuthzRequest = async () => { + setAuthzResult(""); + setAuthzLogs(""); + let reqObj = await createCedarlingAuthzRequestObj(); + chrome.storage.local.get(["cedarlingConfig"], async (cedarlingConfig) => { + let instance: Cedarling; + try { + if (Object.keys(cedarlingConfig).length !== 0) { + await __wbg_init(); + instance = await init(!isEmpty(cedarlingConfig?.cedarlingConfig) ? cedarlingConfig?.cedarlingConfig[0] : undefined); + let result: AuthorizeResult = await instance.authorize(reqObj); + setAuthzResult(result.json_string()) + console.log("result:", result); + let logs = await instance.pop_logs(); + if (logs.length != 0) { + let pretty_logs = logs.map(log => JSON.stringify(log, null, 2)); + setAuthzLogs(pretty_logs.toString()); + } + + } + } catch (err) { + setAuthzResult(err); + console.log("err:", err); + let logs = await instance.pop_logs(); + if (logs.length != 0) { + let pretty_logs = logs.map(log => JSON.stringify(log, null, 2)); + setAuthzLogs(pretty_logs.toString()); + } + } + + }); + + } + + const createCedarlingAuthzRequestObj = async () => { + let reqObj = { tokens: { access_token: '', id_token: '', userinfo_token: '' }, action: "", resource: {}, context: {} }; + if (accessToken) { + reqObj.tokens.access_token = (!!data ? data?.access_token : ''); + } + + if (idToken) { + reqObj.tokens.id_token = (!!data ? data?.id_token : ''); + } + + if (userInfoToken) { + reqObj.tokens.userinfo_token = (!!data ? data?.userDetails : ''); + } + + //reqObj.tokens.access_token = 'eyJraWQiOiJjb25uZWN0X2Y5YTAwN2EyLTZkMGItNDkyYS05MGNkLWYwYzliMWMyYjVkYl9zaWdfcnMyNTYiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJxenhuMVNjcmI5bFd0R3hWZWRNQ2t5LVFsX0lMc3BaYVFBNmZ5dVlrdHcwIiwiY29kZSI6IjNlMmEyMDEyLTA5OWMtNDY0Zi04OTBiLTQ0ODE2MGMyYWIyNSIsImlzcyI6Imh0dHBzOi8vYWNjb3VudC5nbHV1Lm9yZyIsInRva2VuX3R5cGUiOiJCZWFyZXIiLCJjbGllbnRfaWQiOiJkN2Y3MWJlYS1jMzhkLTRjYWYtYTFiYS1lNDNjNzRhMTFhNjIiLCJhdWQiOiJkN2Y3MWJlYS1jMzhkLTRjYWYtYTFiYS1lNDNjNzRhMTFhNjIiLCJhY3IiOiJzaW1wbGVfcGFzc3dvcmRfYXV0aCIsIng1dCNTMjU2IjoiIiwibmJmIjoxNzMxOTUzMDMwLCJzY29wZSI6WyJyb2xlIiwib3BlbmlkIiwicHJvZmlsZSIsImVtYWlsIl0sImF1dGhfdGltZSI6MTczMTk1MzAyNywiZXhwIjoxNzMyMTIxNDYwLCJpYXQiOjE3MzE5NTMwMzAsImp0aSI6InVaVWgxaERVUW82UEZrQlBud3BHemciLCJ1c2VybmFtZSI6IkRlZmF1bHQgQWRtaW4gVXNlciIsInN0YXR1cyI6eyJzdGF0dXNfbGlzdCI6eyJpZHgiOjMwNiwidXJpIjoiaHR0cHM6Ly9qYW5zLnRlc3QvamFucy1hdXRoL3Jlc3R2MS9zdGF0dXNfbGlzdCJ9fX0.Pt-Y7F-hfde_WP7ZYwyvvSS11rKYQWGZXTzjH_aJKC5VPxzOjAXqI3Igr6gJLsP1aOd9WJvOPchflZYArctopXMWClbX_TxpmADqyCMsz78r4P450TaMKj-WKEa9cL5KtgnFa0fmhZ1ZWolkDTQ_M00Xr4EIvv4zf-92Wu5fOrdjmsIGFot0jt-12WxQlJFfs5qVZ9P-cDjxvQSrO1wbyKfHQ_txkl1GDATXsw5SIpC5wct92vjAVm5CJNuv_PE8dHAY-KfPTxOuDYBuWI5uA2Yjd1WUFyicbJgcmYzUSVt03xZ0kQX9dxKExwU2YnpDorfwebaAPO7G114Bkw208g'; + //reqObj.tokens.id_token = 'eyJraWQiOiJjb25uZWN0X2Y5YTAwN2EyLTZkMGItNDkyYS05MGNkLWYwYzliMWMyYjVkYl9zaWdfcnMyNTYiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiYnhhQ1QwWlFYYnY0c2J6alNEck5pQSIsInN1YiI6InF6eG4xU2NyYjlsV3RHeFZlZE1Da3ktUWxfSUxzcFphUUE2Znl1WWt0dzAiLCJhbXIiOltdLCJpc3MiOiJodHRwczovL2FjY291bnQuZ2x1dS5vcmciLCJub25jZSI6IjI1YjJiMTZiLTMyYTItNDJkNi04YThlLWU1ZmE5YWI4ODhjMCIsInNpZCI6IjZkNDQzNzM0LWI3YTItNGVkOC05ZDNhLTE2MDZkMmY5OTI0NCIsImphbnNPcGVuSURDb25uZWN0VmVyc2lvbiI6Im9wZW5pZGNvbm5lY3QtMS4wIiwiYXVkIjoiZDdmNzFiZWEtYzM4ZC00Y2FmLWExYmEtZTQzYzc0YTExYTYyIiwiYWNyIjoic2ltcGxlX3Bhc3N3b3JkX2F1dGgiLCJjX2hhc2giOiJWOGg0c085Tnp1TEthd1BPLTNETkxBIiwibmJmIjoxNzMxOTUzMDMwLCJhdXRoX3RpbWUiOjE3MzE5NTMwMjcsImV4cCI6MTczMTk1NjYzMCwiZ3JhbnQiOiJhdXRob3JpemF0aW9uX2NvZGUiLCJpYXQiOjE3MzE5NTMwMzAsImp0aSI6ImlqTFpPMW9vUnlXcmdJbjdjSWROeUEiLCJzdGF0dXMiOnsic3RhdHVzX2xpc3QiOnsiaWR4IjozMDcsInVyaSI6Imh0dHBzOi8vamFucy50ZXN0L2phbnMtYXV0aC9yZXN0djEvc3RhdHVzX2xpc3QifX19.Nw7MRaJ5LtDak_LdEjrICgVOxDwd1p1I8WxD7IYw0_mKlIJ-J_78rGPski9p3L5ZNCpXiHtVbnhc4lJdmbh-y6mrD3_EY_AmjK50xpuf6YuUuNVtFENCSkj_irPLkIDG65HeZherWsvH0hUn4FVGv8Sw9fjny9Doi-HGHnKg9Qvphqre1U8hCphCVLQlzXAXmBkbPOC8tDwId5yigBKXP50cdqDcT-bjXf9leIdGgq0jxb57kYaFSElprLN9nUygM4RNCn9mtmo1l4IsdTlvvUb3OMAMQkRLfMkiKBjjeSF3819mYRLb3AUBaFH16ZdHFBzTSB6oA22TYpUqOLihMg'; + //reqObj.tokens.userinfo_token = 'eyJraWQiOiJjb25uZWN0X2Y5YTAwN2EyLTZkMGItNDkyYS05MGNkLWYwYzliMWMyYjVkYl9zaWdfcnMyNTYiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJxenhuMVNjcmI5bFd0R3hWZWRNQ2t5LVFsX0lMc3BaYVFBNmZ5dVlrdHcwIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInJvbGUiOlsiQ2FzYUFkbWluIl0sImlzcyI6Imh0dHBzOi8vYWNjb3VudC5nbHV1Lm9yZyIsImdpdmVuX25hbWUiOiJBZG1pbiIsIm1pZGRsZV9uYW1lIjoiQWRtaW4iLCJpbnVtIjoiYTZhNzAzMDEtYWY0OS00OTAxLTk2ODctMGJjZGNmNGUzNGZhIiwiY2xpZW50X2lkIjoiZDdmNzFiZWEtYzM4ZC00Y2FmLWExYmEtZTQzYzc0YTExYTYyIiwiYXVkIjoiZDdmNzFiZWEtYzM4ZC00Y2FmLWExYmEtZTQzYzc0YTExYTYyIiwidXBkYXRlZF9hdCI6MTczMTY5ODEzNSwibmFtZSI6IkRlZmF1bHQgQWRtaW4gVXNlciIsIm5pY2tuYW1lIjoiQWRtaW4iLCJmYW1pbHlfbmFtZSI6IlVzZXIiLCJqdGkiOiJPSW4zZzFTUFNEU0tBWUR6RU5Wb3VnIiwiZW1haWwiOiJhZG1pbkBqYW5zLnRlc3QiLCJqYW5zQWRtaW5VSVJvbGUiOlsiYXBpLWFkbWluIl19.CIahQtRpoTkIQx8KttLPIKH7gvGG8OmYCMzz7wch6k792DVYQG1R7q3sS9Ema1rO5Fm_GgjOsR0yTTMKsyhHDLBwkDd3cnMLgsh2AwVFZvxtpafTlUAPfjvMAy9YTtkPcY6rNUhsYLSSOA83kt6pHdIv5nI-G6ybqgg-bLBRpwZDoOV0TulRhmuukdiuugTXHT6Bb-K3ZeYs8CwewztnxoFTSDghSzq7VZIraV8SLTBLx5_xswn9mefamyB2XNN3o6vXuMyf4BEbYSCuJ3pu6YtNgfyWwt9cF8PYe4PVLoXZuJKN-cy4qrtgy43QXPCg96jSQUJqgLb5ZL5_3udm2Q'; + + reqObj.action = action; + reqObj.context = context; + reqObj.resource = resource; + + chrome.storage.local.set({ authzRequest: reqObj }); + return reqObj; + } + async function logout() { setLoading(true); try { @@ -54,6 +155,10 @@ const UserDetails = ({data, notifyOnDataChange}) => { notifyOnDataChange("true"); } + function isEmpty(value) { + return (value == null || value.length === 0); + } + return (
@@ -64,25 +169,155 @@ const UserDetails = ({data, notifyOnDataChange}) => {
{data?.displayToken ? <> + + } + aria-controls="panel1-content" + id="panel1-header" + > + Access Token + + + +
+

{showMoreAT ? (!!data ? data?.access_token : '') : (!!data ? data?.access_token.substring(0, 250).concat(' ...') : '')}

+ setShowMoreAT(!showMoreAT)}>{showMoreAT ? "Show less" : "Show more"} +
+
+
+ + } + aria-controls="panel1-content" + id="panel1-header" + > + Id Token + + + +
+

{showMoreIdToken ? (!!data ? data?.id_token : '') : (!!data ? data?.id_token.substring(0, 250).concat(' ...') : '')}

+ setShowMoreIdToken(!showMoreIdToken)}>{showMoreIdToken ? "Show less" : "Show more"} +
+
+
+ + : ''} + + } + aria-controls="panel1-content" + id="panel1-header" + > + User Details + +
- Access Token -

{showMoreAT ? (!!data ? data?.access_token : '') : (!!data ? data?.access_token.substring(0, 250).concat(' ...') : '')}

- setShowMoreAT(!showMoreAT)}>{showMoreAT ? "Show less" : "Show more"} + User Details +

{showMoreUI ? (!!data ? data?.userDetails : '') : (!!data ? data?.userDetails.substring(0, 250).concat(' ...') : '')}

+ setShowMoreUI(!showMoreUI)}>{showMoreUI ? "Show less" : "Show more"}
-
- Id Token -

{showMoreIdToken ? (!!data ? data?.id_token : '') : (!!data ? data?.id_token.substring(0, 250).concat(' ...') : '')}

- setShowMoreIdToken(!showMoreIdToken)}>{showMoreIdToken ? "Show less" : "Show more"} + + + {cedarlingBootstrapPresent ? + + } + aria-controls="panel1-content" + id="panel1-header" + > + Cedarling Authz Request Form + + +
+ Principal + setAccessToken(!accessToken)} />} label="Access Token" /> + setUserInfoToken(!userInfoToken)} />} label="Userinfo Token" /> + setIdToken(!idToken)} />} label="Id Token" /> + + { + setAction(e.target.value); + }} + /> + Resource + + Context + +
+
- - : ''} -
- User Details -

{showMoreUI ? (!!data ? data?.userDetails : '') : (!!data ? data?.userDetails.substring(0, 250).concat(' ...') : '')}

- setShowMoreUI(!showMoreUI)}>{showMoreUI ? "Show less" : "Show more"} -
+
+
: ''} + {!!authzResult ? + + } + aria-controls="panel1-content" + id="panel1-header" + > + Cedarling Authz Result + + + + + + : ''} + {!!authzLogs ? + + } + aria-controls="panel2-content" + id="panel2-header" + > + Cedarling Authz Logs + + + + + + : ''} +
- +
) }; diff --git a/demos/jans-tarp/src/static/chrome/manifest.json b/demos/jans-tarp/src/static/chrome/manifest.json index 2cb920ca3c3..5dbed7042ff 100644 --- a/demos/jans-tarp/src/static/chrome/manifest.json +++ b/demos/jans-tarp/src/static/chrome/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "jans-tarp", - "version": "0.0.0-nightly", + "version": "1.0.0", "version_name": "nightly", "description": "Relying Party tool in form of a Chrome Extension. Please note that the manifest version field should be one to four dot-separated integers identifying the version of this extension. The descriptive version string can be stated in the `version_name` field. For more details see https://developer.chrome.com/docs/extensions/reference/manifest/version.", "icons": { @@ -24,5 +24,8 @@ "*://*/*" ], "options_page": "options.html", - "incognito": "split" + "incognito": "split", + "content_security_policy": { + "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';" + } } \ No newline at end of file diff --git a/demos/jans-tarp/src/static/firefox/manifest.json b/demos/jans-tarp/src/static/firefox/manifest.json index e30988c67a1..0ace852b544 100644 --- a/demos/jans-tarp/src/static/firefox/manifest.json +++ b/demos/jans-tarp/src/static/firefox/manifest.json @@ -27,5 +27,8 @@ "gecko": { "id": "jans-tarp@gluu.org" } + }, + "content_security_policy": { + "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';" } } \ No newline at end of file