diff --git a/Sample-01/api-server.js b/Sample-01/api-server.js index 4e946daa..42db266d 100644 --- a/Sample-01/api-server.js +++ b/Sample-01/api-server.js @@ -2,7 +2,12 @@ const express = require("express"); const cors = require("cors"); const morgan = require("morgan"); const helmet = require("helmet"); -const { auth } = require("express-oauth2-jwt-bearer"); +const { + auth, + InvalidTokenError, + InvalidRequestError, + InsufficientScopeError +} = require("express-oauth2-jwt-bearer"); const authConfig = require("./src/auth_config.json"); const app = express(); @@ -11,11 +16,7 @@ const port = process.env.API_PORT || 3001; const appPort = process.env.SERVER_PORT || 3000; const appOrigin = authConfig.appOrigin || `http://localhost:${appPort}`; -if ( - !authConfig.domain || - !authConfig.audience || - authConfig.audience === "YOUR_API_IDENTIFIER" -) { +if (!authConfig.domain || !authConfig.audience || authConfig.audience === "YOUR_API_IDENTIFIER") { console.log( "Exiting: Please make sure that auth_config.json is in place and populated with valid domain and audience values" ); @@ -27,16 +28,35 @@ app.use(morgan("dev")); app.use(helmet()); app.use(cors({ origin: appOrigin })); -const checkJwt = auth({ - audience: authConfig.audience, - issuerBaseURL: `https://${authConfig.domain}/`, - algorithms: ["RS256"], -}); +app.use( + auth({ + audience: authConfig.audience, + issuerBaseURL: `https://${authConfig.domain}/`, + algorithms: ["RS256"], + }) +); -app.get("/api/external", checkJwt, (req, res) => { +app.get("/api/external", (req, res) => { res.send({ msg: "Your access token was successfully validated!", }); }); +// Custom error handler that will turn the errors from express-oauth2-jwt-bearer into a JSON object +// for the UI to handle +app.use((err, req, res, next) => { + if ( + err instanceof InvalidTokenError || + err instanceof InvalidRequestError || + err instanceof InsufficientScopeError + ) { + return res.status(err.status).send({ + error: err.code, + message: err.message, + }); + } + + res.send(err); +}); + app.listen(port, () => console.log(`API Server listening on port ${port}`)); diff --git a/Sample-01/src/components/Highlight.js b/Sample-01/src/components/Highlight.js index 7bdecf31..f8a17dc9 100644 --- a/Sample-01/src/components/Highlight.js +++ b/Sample-01/src/components/Highlight.js @@ -1,73 +1,23 @@ -import React, { Component } from "react"; -import PropTypes from "prop-types"; - -import hljs from "highlight.js"; -import "highlight.js/styles/monokai-sublime.css"; - -const registeredLanguages = {}; - -class Highlight extends Component { - constructor(props) { - super(props); - - this.state = { loaded: false }; - this.codeNode = React.createRef(); - } - - componentDidMount() { - const { language } = this.props; - - if (language && !registeredLanguages[language]) { - try { - const newLanguage = require(`highlight.js/lib/languages/${language}`); - hljs.registerLanguage(language, newLanguage); - registeredLanguages[language] = true; - - this.setState({ loaded: true }, this.highlight); - } catch (e) { - console.error(e); - throw Error(`Cannot register the language ${language}`); - } - } else { - this.setState({ loaded: true }); - } - } - - componentDidUpdate() { - this.highlight(); - } - - highlight = () => { - this.codeNode && - this.codeNode.current && - hljs.highlightBlock(this.codeNode.current); - }; - - render() { - const { language, children } = this.props; - const { loaded } = this.state; - - if (!loaded) { - return null; - } - - return ( -
-        
-          {children}
-        
-      
- ); - } -} - -Highlight.propTypes = { - children: PropTypes.node.isRequired, - language: PropTypes.string, -}; - -Highlight.defaultProps = { - language: "json", +import React, { useEffect, useRef } from 'react'; + +import hljs from 'highlight.js'; +import 'highlight.js/styles/monokai-sublime.css'; + +const Highlight = (props) => { + const { text, language = 'json' } = props; + + const codeNode = useRef(null); + useEffect(() => { + hljs.highlightElement(codeNode.current); + }, [text]); + + return ( +
+      
+        {text}
+      
+    
+ ); }; -export default Highlight; +export default Highlight; \ No newline at end of file diff --git a/Sample-01/src/views/ExternalApi.js b/Sample-01/src/views/ExternalApi.js index 4f3c1d51..882d7e28 100644 --- a/Sample-01/src/views/ExternalApi.js +++ b/Sample-01/src/views/ExternalApi.js @@ -10,8 +10,10 @@ export const ExternalApiComponent = () => { const [state, setState] = useState({ showResult: false, - apiMessage: "", + showApiError: false, error: null, + apiMessage: "", + apiError: null, }); const { @@ -64,12 +66,27 @@ export const ExternalApiComponent = () => { }, }); + if (!response.ok) { + const apiError = response.headers.get('content-type')?.includes('application/json') + ? JSON.stringify(await response.json(), null, 2) + : await response.text(); + setState({ + ...state, + showApiError: true, + showResult: false, + apiError + }); + return; + } + const responseData = await response.json(); setState({ ...state, showResult: true, apiMessage: responseData, + apiError: null, + showApiError: false }); } catch (error) { setState({ @@ -185,9 +202,14 @@ export const ExternalApiComponent = () => { {state.showResult && (
Result
- - {JSON.stringify(state.apiMessage, null, 2)} - + +
+ )} + + {state.showApiError && ( +
+
Error
+
)} diff --git a/Sample-01/src/views/Profile.js b/Sample-01/src/views/Profile.js index 9c85922a..cb29b423 100644 --- a/Sample-01/src/views/Profile.js +++ b/Sample-01/src/views/Profile.js @@ -24,7 +24,7 @@ export const ProfileComponent = () => { - {JSON.stringify(user, null, 2)} + );