github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/api_add_user_u2f_token.go (about) 1 // Copyright 2024 Paul Greenberg greenpau@outlook.com 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package authn 16 17 import ( 18 "context" 19 "net/http" 20 21 "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" 22 "github.com/greenpau/go-authcrunch/pkg/ids" 23 "github.com/greenpau/go-authcrunch/pkg/requests" 24 "github.com/greenpau/go-authcrunch/pkg/tagging" 25 "github.com/greenpau/go-authcrunch/pkg/user" 26 ) 27 28 // AddUserUniSecFactorToken adds U2F token to user identity. 29 func (p *Portal) AddUserUniSecFactorToken( 30 ctx context.Context, 31 w http.ResponseWriter, 32 r *http.Request, 33 rr *requests.Request, 34 parsedUser *user.User, 35 resp map[string]interface{}, 36 usr *user.User, 37 backend ids.IdentityStore, 38 bodyData map[string]interface{}) error { 39 40 var tokenTitle, tokenDescription string 41 var tokenLabels []string = []string{} 42 var tokenTags []tagging.Tag = []tagging.Tag{} 43 44 // Validate inputs. 45 if v, exists := bodyData["webauthn_register"]; exists { 46 rr.WebAuthn.Register = v.(string) 47 } else { 48 resp["message"] = "Profile API did not find webauthn_register in the request payload" 49 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 50 } 51 if v, exists := bodyData["webauthn_challenge"]; exists { 52 rr.WebAuthn.Challenge = v.(string) 53 } else { 54 resp["message"] = "Profile API did not find webauthn_challenge in the request payload" 55 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 56 } 57 if v, exists := bodyData["title"]; exists { 58 tokenTitle = v.(string) 59 } else { 60 resp["message"] = "Profile API did not find title in the request payload" 61 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 62 } 63 if v, exists := bodyData["description"]; exists { 64 tokenDescription = v.(string) 65 } else { 66 resp["message"] = "Profile API did not find description in the request payload" 67 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 68 } 69 if extractedTokenTags, err := tagging.ExtractTags(bodyData); err == nil { 70 for _, extractedTokenTag := range extractedTokenTags { 71 tokenTags = append(tokenTags, *extractedTokenTag) 72 } 73 } else { 74 resp["message"] = "Profile API find malformed tags in the request payload" 75 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 76 } 77 if extractedTokenLabels, err := tagging.ExtractLabels(bodyData); err == nil { 78 tokenLabels = extractedTokenLabels 79 } else { 80 resp["message"] = "Profile API find malformed tags in the request payload" 81 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 82 } 83 84 // Validate data. 85 if !tokenIssuerRegexPattern.MatchString(tokenTitle) { 86 resp["message"] = "Profile API found non-compliant token title value" 87 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 88 } 89 if !tokenDescriptionRegexPattern.MatchString(tokenDescription) && (tokenDescription != "") { 90 resp["message"] = "Profile API found non-compliant token description value" 91 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 92 } 93 94 rr.MfaToken.Type = "u2f" 95 rr.MfaToken.Comment = tokenTitle 96 rr.MfaToken.Description = tokenDescription 97 rr.MfaToken.Tags = tokenTags 98 rr.MfaToken.Labels = tokenLabels 99 100 if err := backend.Request(operator.AddMfaToken, rr); err != nil { 101 resp["message"] = "Profile API failed to add token to identity store" 102 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 103 } 104 105 resp["entry"] = "Created" 106 return handleAPIProfileResponse(w, rr, http.StatusOK, resp) 107 }