github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/api_fetch_user_uni_sec_factor_ver_params.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 "encoding/base64" 20 "fmt" 21 "net/http" 22 "strings" 23 24 "github.com/greenpau/go-authcrunch/pkg/identity" 25 "github.com/greenpau/go-authcrunch/pkg/ids" 26 "github.com/greenpau/go-authcrunch/pkg/requests" 27 "github.com/greenpau/go-authcrunch/pkg/user" 28 "github.com/greenpau/go-authcrunch/pkg/util" 29 ) 30 31 // FetchUserUniSecFactorVerParams fetches U2F authenticator verification parameters. 32 func (p *Portal) FetchUserUniSecFactorVerParams( 33 ctx context.Context, 34 w http.ResponseWriter, 35 r *http.Request, 36 rr *requests.Request, 37 parsedUser *user.User, 38 resp map[string]interface{}, 39 usr *user.User, 40 backend ids.IdentityStore, 41 bodyData map[string]interface{}) error { 42 43 rr.MfaToken.Type = "u2f" 44 45 // Validate inputs. 46 if v, exists := bodyData["webauthn_register"]; exists { 47 rr.WebAuthn.Register = v.(string) 48 } else { 49 resp["message"] = "Profile API did not find webauthn_register in the request payload" 50 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 51 } 52 if v, exists := bodyData["webauthn_challenge"]; exists { 53 rr.WebAuthn.Challenge = v.(string) 54 } else { 55 resp["message"] = "Profile API did not find webauthn_challenge in the request payload" 56 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 57 } 58 59 params := make(map[string]interface{}) 60 allowedCredential := make(map[string]interface{}) 61 62 token, err := identity.NewMfaToken(rr) 63 if err != nil { 64 resp["message"] = fmt.Errorf("the Profile API received malformed U2F token in the request payload: %v", err) 65 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 66 } 67 68 if token.Parameters == nil { 69 resp["message"] = "Profile API received malformed U2F token with empty parameters in the request payload" 70 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 71 } 72 73 for _, k := range []string{"id", "transports", "type"} { 74 if _, exists := token.Parameters["u2f_"+k]; !exists { 75 resp["message"] = fmt.Errorf("the Profile API received malformed U2F token with empty %s parameter in the request payload", k) 76 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 77 } 78 } 79 80 randomStr := util.GetRandomStringFromRange(64, 92) 81 params["challenge"] = strings.TrimRight(base64.StdEncoding.EncodeToString([]byte(randomStr)), "=") 82 params["rp_name"] = "AuthCrunch" 83 // params["rp_id"] = "auth.authcrunch.com" 84 params["timeout"] = 60000 85 params["user_verification"] = "discouraged" 86 params["ext_uvm"] = false 87 params["ext_loc"] = false 88 params["ext_tx_auth_simple"] = "Could you please verify your authentication token?" 89 allowedCredential["id"] = token.Parameters["u2f_id"] 90 allowedCredential["type"] = token.Parameters["u2f_type"] 91 allowedCredential["transports"] = strings.Split(token.Parameters["u2f_transports"], ",") 92 var allowedCredentials []map[string]interface{} 93 allowedCredentials = append(allowedCredentials, allowedCredential) 94 params["credentials"] = allowedCredentials 95 resp["entry"] = params 96 return handleAPIProfileResponse(w, rr, http.StatusOK, resp) 97 }