Skip to content

Commit

Permalink
Merge branch 'main' into doc-stable-release-update
Browse files Browse the repository at this point in the history
  • Loading branch information
ossdhaval authored Jan 17, 2025
2 parents b3f2d7a + 261c936 commit fef8724
Show file tree
Hide file tree
Showing 64 changed files with 5,052 additions and 3,471 deletions.
3 changes: 2 additions & 1 deletion demos/jans-tarp/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
dist
release
package-lock.json
package-lock.json
src/wasm
12 changes: 7 additions & 5 deletions demos/jans-tarp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 decision post-authentication.

## Supporting Browser

Expand All @@ -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

Expand Down
5 changes: 4 additions & 1 deletion demos/jans-tarp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down Expand Up @@ -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",
Expand All @@ -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"
}
}
200 changes: 200 additions & 0 deletions demos/jans-tarp/src/options/addCedarlingConfig.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<React.Fragment>
<Dialog
open={open}
onClose={handleClose}
PaperProps={{
component: 'form',
onSubmit: (event) => {
event.preventDefault();
},
}}
className="form-container"
>
<DialogTitle>Add Cedarling Configuration</DialogTitle>
{loading ? (
<div className="loader-overlay">
<CircularProgress color="success" />
</div>
) : (
""
)}
<DialogContent>
<DialogContentText>
Submit below details.
</DialogContentText>
<Stack
component="form"
sx={{
width: '75ch',
}}
spacing={2}
noValidate
autoComplete="off"
>
{(!!errorMessage || errorMessage !== '') ?
<Alert severity="error">{errorMessage}</Alert> : ''
}
<RadioGroup
row
aria-labelledby="demo-row-radio-buttons-group-label"
name="row-radio-buttons-group"
defaultValue="json"
>
<FormControlLabel value="json" control={<Radio onClick={() => { setErrorMessage(''); setInputSelection("json"); }} color="success" />} label="JSON" />
<FormControlLabel value="url" control={<Radio onClick={() => { setErrorMessage(''); setInputSelection("url") }} />} label="URL" />
</RadioGroup>
{inputSelection === 'json' ?
<JsonEditor
data={bootstrap}
setData={setBootstrap}
rootName="bootstrapConfig"
/>
: ''}
{inputSelection === 'url' ?
<TextField
error={errorMessage.length !== 0}
autoFocus
required
margin="dense"
id="bootstrapUrl"
name="bootstrapUrl"
label="Bootstrap Configuration URL"
type="text"
fullWidth
variant="outlined"
helperText={errorMessage}
onBlur={(e) => {
validateBootstrap(e);
}}
/> : ''}
</Stack>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button type="submit" onClick={saveBootstrap}>Save</Button>
</DialogActions>
</Dialog>
</React.Fragment>
);
}
1 change: 1 addition & 0 deletions demos/jans-tarp/src/options/authFlowInputs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ export default function AuthFlowInputs({ isOpen, handleDialog, client, notifyOnD
<TextField {...params} label="Scopes" />
)}
/>

<FormControlLabel control={<Checkbox color="success" onChange={() => setDisplayToken(!displayToken)}/>} label="Display Access Token and ID Token after authentication" />
</Stack>
</DialogContent>
Expand Down
Loading

0 comments on commit fef8724

Please sign in to comment.