import React, { Component } from 'react'; import { Button, Form, Modal, Dropdown, Input, TextArea, Label } from 'semantic-ui-react'; import { generateToken, parse } from './utils/jwt'; export enum AUTH_MODE { API_KEY = 'API_KEY', AMAZON_COGNITO_USER_POOLS = 'AMAZON_COGNITO_USER_POOLS', OPENID_CONNECT = 'OPENID_CONNECT', AWS_IAM = 'AWS_IAM', } type State = { currentCognitoToken?: string; currentOIDCToken: string; currentOIDCTokenDecoded?: string; currentAuthMode: AUTH_MODE; userName?: string; userGroups: string[]; email?: string; additionalFields?: string; issuer?: string; apiKey?: string; possibleGroups: string[]; isOpen: boolean; supportedAuthModes: AUTH_MODE[]; oidcTokenError: string; iamRole: 'auth' | 'unAuth'; }; type Props = { onClose: Function; authModes: AUTH_MODE[]; selectedAuthMode: AUTH_MODE; currentCognitoToken?: string; currentOIDCToken?: string; iamRole?: 'Auth' | 'UnAuth'; apiKey?: string; }; export class AuthModal extends Component { state: State = { currentCognitoToken: '', currentOIDCTokenDecoded: '', currentOIDCToken: '', userName: '', issuer: '', userGroups: [], apiKey: '', possibleGroups: [], email: '', supportedAuthModes: [AUTH_MODE.API_KEY], isOpen: true, currentAuthMode: AUTH_MODE.API_KEY, oidcTokenError: '', iamRole: 'auth', }; constructor(props) { super(props); const decodedToken = this.parseJWTToken(this.props.currentCognitoToken) || {}; let state = { userName: decodedToken['cognito:username'] || '', userGroups: decodedToken['cognito:groups'] || [], issuer: decodedToken['iss'], email: decodedToken['email'], possibleGroups: decodedToken['cognito:groups'] || [], }; const jwtFieldsToFilter = [ 'cognito:username', 'cognito:groups', 'iss', 'email', 'sub', 'aud', 'exp', 'event_id', 'iat', 'algorithm', 'auth_time', ]; const additionalFields = Object.keys(decodedToken) .filter((k) => !jwtFieldsToFilter.includes(k)) .reduce((acc, k) => ({ ...acc, [k]: decodedToken[k] }), {}); this.state = { ...this.state, ...state, additionalFields: JSON.stringify(additionalFields, null, 4), currentCognitoToken: this.props.currentCognitoToken || '', currentOIDCToken: this.props.currentOIDCToken || '', currentOIDCTokenDecoded: JSON.stringify(this.parseJWTToken(this.props.currentOIDCToken), null, 4) || '', apiKey: props.apiKey || '', supportedAuthModes: this.props.authModes, currentAuthMode: props.selectedAuthMode, iamRole: props.iamRole || 'Auth', }; this.onClose = this.onClose.bind(this); this.onGroupChange = this.onGroupChange.bind(this); this.onGroupAdd = this.onGroupAdd.bind(this); this.onGenerate = this.onGenerate.bind(this); this.changeAPIKey = this.changeAPIKey.bind(this); this.changeEmail = this.changeEmail.bind(this); this.onUserNameChange = this.onUserNameChange.bind(this); this.onOIDCTokenChange = this.onOIDCTokenChange.bind(this); this.onAuthModeChange = this.onAuthModeChange.bind(this); } onClose() { const result = { authMode: this.state.currentAuthMode, apiKey: this.state.currentAuthMode === AUTH_MODE.API_KEY ? this.state.apiKey : null, cognitoToken: this.state.currentAuthMode === AUTH_MODE.AMAZON_COGNITO_USER_POOLS ? this.state.currentCognitoToken : null, OIDCToken: this.state.currentAuthMode === AUTH_MODE.OPENID_CONNECT ? this.state.currentOIDCToken : null, // We have no data for IAM to store, so we just store a constant string for now iam: this.state.currentAuthMode === AUTH_MODE.AWS_IAM ? 'AWS4-HMAC-SHA256 IAMAuthorized' : null, iamRole: this.state.iamRole, }; if (this.props.onClose) { this.props.onClose(result); } } onGroupChange(ev, data) { this.setState({ userGroups: data.value, }); } onGroupAdd(ev, data) { this.setState({ possibleGroups: [...this.state.possibleGroups, data.value], }); } onUserNameChange(ev, data) { this.setState({ userName: data.value, }); } onOIDCTokenChange(ev, data) { this.setState({ currentOIDCTokenDecoded: data.value, }); } onAuthModeChange(ev, data) { this.setState({ currentAuthMode: data.value, }); } onIAMRoleChange(ev, data) { this.setState({ iamRole: data.value, }); } changeEmail(ev, data) { this.setState({ email: data.value, }); } onAdditionalFieldChange = (ev, data) => { this.setState({ additionalFields: data.value, }); }; changeAPIKey(ev, data) { this.setState({ apiKey: data.value, }); } render() { let formContent; let actionText = 'Save'; if (this.state.currentAuthMode === AUTH_MODE.API_KEY) { formContent = ( <> ); } else if (this.state.currentAuthMode === AUTH_MODE.AMAZON_COGNITO_USER_POOLS) { actionText = 'Generate Token'; formContent = ( <> ({ key: g, value: g, text: g, }))} selection fluid multiple allowAdditions value={this.state.userGroups} onAddItem={this.onGroupAdd} onChange={this.onGroupChange} />