From 2a551bc8c0676201abdd82d7cf2c4e5e9d9d3a79 Mon Sep 17 00:00:00 2001 From: Tyler Noblett Date: Tue, 16 May 2023 17:46:13 -0400 Subject: [PATCH] Change 'key' to 'credential' (#833) * change key name to credential name * change other instances of key to credential --- backend/authschemes/webauthn/dtos.go | 10 +-- backend/authschemes/webauthn/types.go | 30 +++---- backend/authschemes/webauthn/webauthn.go | 68 +++++++-------- backend/authschemes/webauthn/webauthnuser.go | 52 ++++++------ .../src/authschemes/webauthn/linker/index.tsx | 12 +-- .../src/authschemes/webauthn/login/index.tsx | 4 +- frontend/src/authschemes/webauthn/services.ts | 32 ++++---- .../authschemes/webauthn/settings/index.tsx | 82 +++++++++---------- .../webauthn/settings/stylesheet.styl | 4 +- frontend/src/authschemes/webauthn/types.ts | 8 +- 10 files changed, 151 insertions(+), 151 deletions(-) diff --git a/backend/authschemes/webauthn/dtos.go b/backend/authschemes/webauthn/dtos.go index 3e6aebfc4..352901a6e 100644 --- a/backend/authschemes/webauthn/dtos.go +++ b/backend/authschemes/webauthn/dtos.go @@ -5,11 +5,11 @@ package webauthn import "time" -type ListKeysOutput struct { - Keys []KeyEntry `json:"keys"` +type ListCredentialsOutput struct { + Credentials []CredentialEntry `json:"credentials"` } -type KeyEntry struct { - KeyName string `json:"keyName"` - DateCreated time.Time `json:"dateCreated"` +type CredentialEntry struct { + CredentialName string `json:"credentialName"` + DateCreated time.Time `json:"dateCreated"` } diff --git a/backend/authschemes/webauthn/types.go b/backend/authschemes/webauthn/types.go index 27f8b4d1e..ad2ed34a4 100644 --- a/backend/authschemes/webauthn/types.go +++ b/backend/authschemes/webauthn/types.go @@ -9,27 +9,27 @@ import ( type RegistrationType int const ( - // CreateOrLinkKey reflects the usecase where - CreateKey RegistrationType = iota - LinkKey - AddKey + // CreateOrLinkCredential reflects the usecase where + CreateCredential RegistrationType = iota + LinkCredential + AddCredential ) type WebAuthnRegistrationInfo struct { - Email string - Username string - FirstName string - LastName string - KeyName string - UserID int64 - RegistrationType RegistrationType - ExistingCredentials []AShirtWebauthnCredential - KeyCreatedDate time.Time + Email string + Username string + FirstName string + LastName string + CredentialName string + UserID int64 + RegistrationType RegistrationType + ExistingCredentials []AShirtWebauthnCredential + CredentialCreatedDate time.Time } type AShirtWebauthnExtension struct { - KeyName string `json:"keyName"` - KeyCreatedDate time.Time `json:"keyCreatedDate"` + CredentialName string `json:"credentialName"` + CredentialCreatedDate time.Time `json:"credentialCreatedDate"` } type AShirtWebauthnCredential struct { diff --git a/backend/authschemes/webauthn/webauthn.go b/backend/authschemes/webauthn/webauthn.go index 8fd14bceb..85c9a5d11 100644 --- a/backend/authschemes/webauthn/webauthn.go +++ b/backend/authschemes/webauthn/webauthn.go @@ -107,8 +107,8 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) Username: dr.FromBody("username").Required().AsString(), FirstName: dr.FromBody("firstName").Required().AsString(), LastName: dr.FromBody("lastName").Required().AsString(), - KeyName: dr.FromBody("keyName").Required().AsString(), - RegistrationType: CreateKey, + CredentialName: dr.FromBody("credentialName").Required().AsString(), + RegistrationType: CreateCredential, } if dr.Error != nil { return nil, dr.Error @@ -194,9 +194,9 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) dr := remux.DissectJSONRequest(r) info := WebAuthnRegistrationInfo{ Username: dr.FromBody("username").Required().AsString(), - KeyName: dr.FromBody("keyName").Required().AsString(), + CredentialName: dr.FromBody("credentialName").Required().AsString(), UserID: callingUserId, - RegistrationType: LinkKey, + RegistrationType: LinkCredential, } if dr.Error != nil { return nil, dr.Error @@ -222,22 +222,22 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) }) })) - remux.Route(r, "GET", "/keys", remux.JSONHandler(func(r *http.Request) (interface{}, error) { + remux.Route(r, "GET", "/credentials", remux.JSONHandler(func(r *http.Request) (interface{}, error) { callingUserID := middleware.UserID(r.Context()) - return a.getKeys(callingUserID, bridge) + return a.getCredentials(callingUserID, bridge) })) - remux.Route(r, "DELETE", "/key/{keyName}", remux.JSONHandler(func(r *http.Request) (interface{}, error) { + remux.Route(r, "DELETE", "/credential/{credentialName}", remux.JSONHandler(func(r *http.Request) (interface{}, error) { callingUserID := middleware.UserID(r.Context()) dr := remux.DissectJSONRequest(r) - keyName := dr.FromURL("keyName").Required().AsString() + credentialName := dr.FromURL("credentialName").Required().AsString() if dr.Error != nil { return nil, dr.Error } - return nil, a.deleteKey(callingUserID, keyName, bridge) + return nil, a.deleteCredential(callingUserID, credentialName, bridge) })) - remux.Route(r, "POST", "/key/add/begin", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + remux.Route(r, "POST", "/credential/add/begin", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { remux.JSONHandler(func(r *http.Request) (interface{}, error) { auth, err := bridge.FindUserAuthByContext(r.Context()) if err != nil { @@ -245,16 +245,16 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) } dr := remux.DissectJSONRequest(r) - keyName := dr.FromBody("keyName").Required().AsString() + credentialName := dr.FromBody("credentialName").Required().AsString() if dr.Error != nil { return nil, dr.Error } info := WebAuthnRegistrationInfo{ Username: auth.Username, - KeyName: keyName, + CredentialName: credentialName, UserID: auth.UserID, - RegistrationType: AddKey, + RegistrationType: AddCredential, } creds, err := a.getExistingCredentials(auth) @@ -267,7 +267,7 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) }).ServeHTTP(w, r) })) - remux.Route(r, "POST", "/key/add/finish", remux.JSONHandler(func(r *http.Request) (interface{}, error) { + remux.Route(r, "POST", "/credential/add/finish", remux.JSONHandler(func(r *http.Request) (interface{}, error) { _, encodedCreds, err := a.validateRegistrationComplete(r, bridge) if err != nil { return nil, backend.WrapError("Unable to validate registration data", err) @@ -280,18 +280,18 @@ func (a WebAuthn) BindRoutes(r *mux.Router, bridge authschemes.AShirtAuthBridge) userAuth.JSONData = helpers.Ptr(string(encodedCreds)) err = bridge.UpdateAuthForUser(userAuth) if err != nil { - return nil, backend.WrapError("Unable to update keys", err) + return nil, backend.WrapError("Unable to update credentials", err) } - // We might want to return a full list of keys. TODO: check if we want that + // We might want to return a full list of credentials. TODO: check if we want that return nil, nil })) } -func (a WebAuthn) getKeys(userID int64, bridge authschemes.AShirtAuthBridge) (*ListKeysOutput, error) { +func (a WebAuthn) getCredentials(userID int64, bridge authschemes.AShirtAuthBridge) (*ListCredentialsOutput, error) { auth, err := bridge.FindUserAuthByUserID(userID) if err != nil { - return nil, backend.WrapError("Unable to get keys", err) + return nil, backend.WrapError("Unable to get credentials", err) } webauthRawCreds := []byte(*auth.JSONData) @@ -300,17 +300,17 @@ func (a WebAuthn) getKeys(userID int64, bridge authschemes.AShirtAuthBridge) (*L return nil, backend.WebauthnLoginError(err, "Unable to parse webauthn credentials") } - results := helpers.Map(creds, func(cred AShirtWebauthnCredential) KeyEntry { - return KeyEntry{ - KeyName: cred.KeyName, - DateCreated: cred.KeyCreatedDate, + results := helpers.Map(creds, func(cred AShirtWebauthnCredential) CredentialEntry { + return CredentialEntry{ + CredentialName: cred.CredentialName, + DateCreated: cred.CredentialCreatedDate, } }) - output := ListKeysOutput{results} + output := ListCredentialsOutput{results} return &output, nil } -func (a WebAuthn) deleteKey(userID int64, keyName string, bridge authschemes.AShirtAuthBridge) error { +func (a WebAuthn) deleteCredential(userID int64, credentialName string, bridge authschemes.AShirtAuthBridge) error { auth, err := bridge.FindUserAuthByUserID(userID) if err != nil { return backend.WrapError("Unable to find user", err) @@ -323,11 +323,11 @@ func (a WebAuthn) deleteKey(userID int64, keyName string, bridge authschemes.ASh } results := helpers.Filter(creds, func(cred AShirtWebauthnCredential) bool { - return cred.KeyName != keyName + return cred.CredentialName != credentialName }) encodedCreds, err := json.Marshal(results) if err != nil { - return backend.WrapError("Unable to delete key", err) + return backend.WrapError("Unable to delete credential", err) } auth.JSONData = helpers.Ptr(string(encodedCreds)) @@ -338,12 +338,12 @@ func (a WebAuthn) deleteKey(userID int64, keyName string, bridge authschemes.ASh func (a WebAuthn) beginRegistration(w http.ResponseWriter, r *http.Request, bridge authschemes.AShirtAuthBridge, info WebAuthnRegistrationInfo) (*protocol.CredentialCreation, error) { var user webauthnUser - if info.RegistrationType == CreateKey { - user = makeNewWebAuthnUser(info.FirstName, info.LastName, info.Email, info.Username, info.KeyName) - } else if info.RegistrationType == LinkKey { - user = makeLinkingWebAuthnUser(info.UserID, info.Username, info.KeyName) - } else { // Add Key - user = makeAddKeyWebAuthnUser(info.UserID, info.KeyName, info.Username, info.ExistingCredentials) + if info.RegistrationType == CreateCredential { + user = makeNewWebAuthnUser(info.FirstName, info.LastName, info.Email, info.Username, info.CredentialName) + } else if info.RegistrationType == LinkCredential { + user = makeLinkingWebAuthnUser(info.UserID, info.Username, info.CredentialName) + } else { // Add Credential + user = makeAddCredentialWebAuthnUser(info.UserID, info.CredentialName, info.Username, info.ExistingCredentials) } credExcludeList := make([]protocol.CredentialDescriptor, len(user.Credentials)) @@ -422,8 +422,8 @@ func (a WebAuthn) validateRegistrationComplete(r *http.Request, bridge authschem } data.UserData.Credentials = append(data.UserData.Credentials, wrapCredential(*cred, AShirtWebauthnExtension{ - KeyName: data.UserData.KeyName, - KeyCreatedDate: data.UserData.KeyCreatedDate, + CredentialName: data.UserData.CredentialName, + CredentialCreatedDate: data.UserData.CredentialCreatedDate, })) encodedCreds, err := json.Marshal(data.UserData.Credentials) diff --git a/backend/authschemes/webauthn/webauthnuser.go b/backend/authschemes/webauthn/webauthnuser.go index 925ba7268..79008099c 100644 --- a/backend/authschemes/webauthn/webauthnuser.go +++ b/backend/authschemes/webauthn/webauthnuser.go @@ -11,42 +11,42 @@ import ( ) type webauthnUser struct { - UserID []byte - AuthnID []byte - UserName string - IconURL string - Credentials []AShirtWebauthnCredential - FirstName string - LastName string - Email string - KeyName string - KeyCreatedDate time.Time + UserID []byte + AuthnID []byte + UserName string + IconURL string + Credentials []AShirtWebauthnCredential + FirstName string + LastName string + Email string + CredentialName string + CredentialCreatedDate time.Time } -func makeNewWebAuthnUser(firstName, lastName, email, username, keyName string) webauthnUser { +func makeNewWebAuthnUser(firstName, lastName, email, username, credentialName string) webauthnUser { return webauthnUser{ - AuthnID: []byte(uuid.New().String()), - UserName: username, - FirstName: firstName, - LastName: lastName, - Email: email, - KeyName: keyName, - KeyCreatedDate: time.Now(), + AuthnID: []byte(uuid.New().String()), + UserName: username, + FirstName: firstName, + LastName: lastName, + Email: email, + CredentialName: credentialName, + CredentialCreatedDate: time.Now(), } } -func makeLinkingWebAuthnUser(userID int64, username, keyName string) webauthnUser { +func makeLinkingWebAuthnUser(userID int64, username, credentialName string) webauthnUser { return webauthnUser{ - UserID: i64ToByteSlice(userID), - AuthnID: []byte(uuid.New().String()), - UserName: username, - KeyName: keyName, - KeyCreatedDate: time.Now(), + UserID: i64ToByteSlice(userID), + AuthnID: []byte(uuid.New().String()), + UserName: username, + CredentialName: credentialName, + CredentialCreatedDate: time.Now(), } } -func makeAddKeyWebAuthnUser(userID int64, username, keyName string, creds []AShirtWebauthnCredential) webauthnUser { - user := makeLinkingWebAuthnUser(userID, username, keyName) +func makeAddCredentialWebAuthnUser(userID int64, username, credentialName string, creds []AShirtWebauthnCredential) webauthnUser { + user := makeLinkingWebAuthnUser(userID, username, credentialName) user.Credentials = creds return user } diff --git a/frontend/src/authschemes/webauthn/linker/index.tsx b/frontend/src/authschemes/webauthn/linker/index.tsx index 560ddf409..337cfa8e4 100644 --- a/frontend/src/authschemes/webauthn/linker/index.tsx +++ b/frontend/src/authschemes/webauthn/linker/index.tsx @@ -19,25 +19,25 @@ export default (props: { }) => { const initialUsername = props.userData.authSchemes.find(s => s.schemeType == 'local')?.username const username = useFormField(initialUsername ?? "") - const keyName = useFormField('') + const credentialName = useFormField('') const [allowUsernameOverride, setOverride] = React.useState(false) const formComponentProps = useForm({ - fields: [username, keyName], + fields: [username, credentialName], onSuccess: () => props.onSuccess(), handleSubmit: async () => { if (username.value === '') { return Promise.reject(new Error("Username must be populated")) } - if (keyName.value === '') { - return Promise.reject(new Error("Key name must be populated")) + if (credentialName.value === '') { + return Promise.reject(new Error("Credential name must be populated")) } let reg = null try { reg = await beginLink({ username: username.value, - keyName: keyName.value, + credentialName: credentialName.value, }) } catch (err) { @@ -79,7 +79,7 @@ export default (props: { return (
- +
) } diff --git a/frontend/src/authschemes/webauthn/login/index.tsx b/frontend/src/authschemes/webauthn/login/index.tsx index c26be5db7..a053998c4 100644 --- a/frontend/src/authschemes/webauthn/login/index.tsx +++ b/frontend/src/authschemes/webauthn/login/index.tsx @@ -106,7 +106,7 @@ const RegisterModal = (props: { lastName: lastNameField.value, email: emailField.value, username: usernameField.value, - keyName: keyNameField.value, + credentialName: keyNameField.value, }) const credOptions = convertToCredentialCreationOptions(reg) @@ -140,7 +140,7 @@ const RegisterModal = (props: { - + ) diff --git a/frontend/src/authschemes/webauthn/services.ts b/frontend/src/authschemes/webauthn/services.ts index e7f3e2523..2f9260168 100644 --- a/frontend/src/authschemes/webauthn/services.ts +++ b/frontend/src/authschemes/webauthn/services.ts @@ -5,8 +5,8 @@ import req from 'src/services/data_sources/backend/request_helper' import { CompletedLoginChallenge, - KeyEntry, - KeyList, + CredentialEntry, + CredentialList, ProvidedCredentialCreationOptions, ProvidedCredentialRequestOptions, WebAuthNRegisterConfirmation, @@ -17,7 +17,7 @@ export async function beginRegistration(i: { username: string, firstName: string, lastName: string - keyName: string + credentialName: string }): Promise { return await req('POST', '/auth/webauthn/register/begin', i) } @@ -38,7 +38,7 @@ export async function finishLogin(i: CompletedLoginChallenge): Promise { export async function beginLink(i: { username: string, - keyName: string + credentialName: string }): Promise { return await req('POST', '/auth/webauthn/link/begin', i) } @@ -47,28 +47,28 @@ export async function finishLinking(i: WebAuthNRegisterConfirmation) { return await req('POST', '/auth/webauthn/link/finish', i) } -export async function beginAddKey(i: { - keyName: string +export async function beginAddCredential(i: { + credentialName: string }): Promise { - return await req('POST', '/auth/webauthn/key/add/begin', i) + return await req('POST', '/auth/webauthn/credential/add/begin', i) } -export async function finishAddKey(i: WebAuthNRegisterConfirmation) { - return await req('POST', '/auth/webauthn/key/add/finish', i) +export async function finishAddCredential(i: WebAuthNRegisterConfirmation) { + return await req('POST', '/auth/webauthn/credential/add/finish', i) } -export async function listWebauthnKeys(): Promise { - const data: KeyList = await req('GET', '/auth/webauthn/keys') +export async function listWebauthnCredentials(): Promise { + const data: CredentialList = await req('GET', '/auth/webauthn/credentials') return { - keys: data.keys.map((key: KeyEntry) => ({ - ...key, - dateCreated: new Date(key.dateCreated) + credentials: data.credentials.map((credential: CredentialEntry) => ({ + ...credential, + dateCreated: new Date(credential.dateCreated) })) } } -export async function deleteWebauthnKey(i: { keyName: string }): Promise { - return await req('DELETE', `/auth/webauthn/key/${i.keyName}`) +export async function deleteWebauthnCredential(i: { credentialName: string }): Promise { + return await req('DELETE', `/auth/webauthn/credential/${i.credentialName}`) } diff --git a/frontend/src/authschemes/webauthn/settings/index.tsx b/frontend/src/authschemes/webauthn/settings/index.tsx index e1e8464da..1a9bae8f9 100644 --- a/frontend/src/authschemes/webauthn/settings/index.tsx +++ b/frontend/src/authschemes/webauthn/settings/index.tsx @@ -9,7 +9,7 @@ import SettingsSection from 'src/components/settings_section' import classnames from 'classnames/bind' import { useForm, useFormField } from 'src/helpers/use_form' import { renderModals, useModal, useWiredData } from 'src/helpers' -import { beginAddKey, deleteWebauthnKey, finishAddKey, listWebauthnKeys } from '../services' +import { beginAddCredential, deleteWebauthnCredential, finishAddCredential, listWebauthnCredentials } from '../services' import Table from 'src/components/table' import Button from 'src/components/button' import { BuildReloadBus } from 'src/helpers/reload_bus' @@ -26,40 +26,40 @@ export default (props: { }) => { const bus = BuildReloadBus() return ( - - - + + + ) } -const KeyList = (props: { +const CredentialList = (props: { onReload: (listener: () => void) => void offReload: (listener: () => void) => void }) => { - const wiredKeys = useWiredData(listWebauthnKeys) + const wiredCredentials = useWiredData(listWebauthnCredentials) React.useEffect(() => { - props.onReload(wiredKeys.reload) - return () => { props.offReload(wiredKeys.reload) } + props.onReload(wiredCredentials.reload) + return () => { props.offReload(wiredCredentials.reload) } }) - const deleteModal = useModal<{ keyName: string }>(mProps => , wiredKeys.reload) + const deleteModal = useModal<{ credentialName: string }>(mProps => , wiredCredentials.reload) return (<> - {wiredKeys.render(data => { + {wiredCredentials.render(data => { return (
- - {data.keys.map(keyEntry => { - const { keyName, dateCreated } = keyEntry +
+ {data.credentials.map(credentialEntry => { + const { credentialName, dateCreated } = credentialEntry return ( - - + +
{keyName}
{credentialName} {toEnUSDate(dateCreated)} @@ -75,34 +75,34 @@ const KeyList = (props: { ) } -const AddKeyButton = (props: { +const AddCredentialButton = (props: { requestReload: () => void }) => { const createModal = useModal(mProps => ( - + ), props.requestReload) return (
- + {renderModals(createModal)}
) } -const AddKeyModal = (props: { +const AddCredentialModal = (props: { onRequestClose: () => void, }) => { - const keyName = useFormField("") + const credentialName = useFormField("") const formComponentProps = useForm({ - fields: [keyName], + fields: [credentialName], handleSubmit: async () => { - if (keyName.value === '') { - return Promise.reject(new Error("Key name must be populated")) + if (credentialName.value === '') { + return Promise.reject(new Error("Credential name must be populated")) } - const reg = await beginAddKey({ - keyName: keyName.value, + const reg = await beginAddCredential({ + credentialName: credentialName.value, }) const credOptions = convertToCredentialCreationOptions(reg) @@ -111,16 +111,16 @@ const AddKeyModal = (props: { if (signed == null || signed.type != 'public-key') { throw new Error("WebAuthn is not supported") } - const pubKeyCred = signed as PublicKeyCredential - const pubKeyResponse = pubKeyCred.response as AuthenticatorAttestationResponse + const pubCredential = signed as PublicKeyCredential + const pubCredentialResponse = pubCredential.response as AuthenticatorAttestationResponse - await finishAddKey({ + await finishAddCredential({ type: 'public-key', - id: pubKeyCred.id, - rawId: encodeAsB64(pubKeyCred.rawId), + id: pubCredential.id, + rawId: encodeAsB64(pubCredential.rawId), response: { - attestationObject: encodeAsB64(pubKeyResponse.attestationObject), - clientDataJSON: encodeAsB64(pubKeyResponse.clientDataJSON), + attestationObject: encodeAsB64(pubCredentialResponse.attestationObject), + clientDataJSON: encodeAsB64(pubCredentialResponse.clientDataJSON), }, }) }, @@ -129,27 +129,27 @@ const AddKeyModal = (props: { return ( - + ) } -const DeleteKeyModal = (props: { - keyName: string, +const DeleteCredentialModal = (props: { + credentialName: string, onRequestClose: () => void, }) => ( deleteWebauthnKey({ keyName: props.keyName })} + challengeText={props.credentialName} + handleSubmit={() => deleteWebauthnCredential({ credentialName: props.credentialName })} onRequestClose={props.onRequestClose} /> ) diff --git a/frontend/src/authschemes/webauthn/settings/stylesheet.styl b/frontend/src/authschemes/webauthn/settings/stylesheet.styl index 751982f7e..c258f1130 100644 --- a/frontend/src/authschemes/webauthn/settings/stylesheet.styl +++ b/frontend/src/authschemes/webauthn/settings/stylesheet.styl @@ -3,13 +3,13 @@ .header margin-bottom: 10px -.user-key +.user-credential background: $darker-background padding: 1px 5px margin: 0 1px border-radius: 3px box-shadow: 0 0 0 1px rgba(#000, 0.5) -.security-keys-section +.security-credentials-section * margin-bottom: 5px diff --git a/frontend/src/authschemes/webauthn/types.ts b/frontend/src/authschemes/webauthn/types.ts index 95d80e4a1..5ab21dfbf 100644 --- a/frontend/src/authschemes/webauthn/types.ts +++ b/frontend/src/authschemes/webauthn/types.ts @@ -56,11 +56,11 @@ export type CompletedLoginChallenge = { } } -export type KeyList = { - keys: Array +export type CredentialList = { + credentials: Array } -export type KeyEntry = { - keyName: string +export type CredentialEntry = { + credentialName: string dateCreated: Date }