func (c *RemoteU2FClient) CompleteRegister(p *PendingRegister) ([]byte, error) { ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute) defer cancel() resp, err := c.c.GetOpResponse(ctx, p.Key) if err != nil { return nil, fmt.Errorf("error registering: %v", err) } var regResp u2f.RegisterResponse if err := json.Unmarshal(resp.Json, ®Resp); err != nil { return nil, fmt.Errorf("invalid response: %s", err) } config := u2f.Config{ // Unfortunately we don't have the attestation certs of many keys, // so skip the check for now. SkipAttestationVerify: true, } reg, err := u2f.Register(regResp, *p.challenge, &config) if err != nil { return nil, fmt.Errorf("u2f.Register error: %v", err) } // We save the marshalled registration object, which we use later to get // it back for authorization purposes. return reg.MarshalBinary() }
func registerResponse(w http.ResponseWriter, r *http.Request) { var regResp u2f.RegisterResponse if err := json.NewDecoder(r.Body).Decode(®Resp); err != nil { http.Error(w, "invalid response: "+err.Error(), http.StatusBadRequest) return } if challenge == nil { http.Error(w, "challenge not found", http.StatusBadRequest) return } reg, err := u2f.Register(regResp, *challenge, nil) if err != nil { log.Printf("u2f.Register error: %v", err) http.Error(w, "error verifying response", http.StatusInternalServerError) return } registration = append(registration, *reg) counter = 0 log.Printf("Registration success: %+v", reg) w.Write([]byte("success")) }
// StoreResponse checks whether, based on the given information, the given // U2F response has addressed the challenge. // // Get the RegisterResponse with e.g. // if err := json.NewDecoder(r.Body).Decode(®Resp); err != nil { // http.Error(w, "invalid response: "+err.Error(), http.StatusBadRequest) // return // } func StoreResponse(ctx appengine.Context, userIdentity string, resp u2f.RegisterResponse) error { // Load the most recent challenge. ckey := makeKey(ctx, userIdentity, "Challenge") var challenge u2f.Challenge if err := datastore.Get(ctx, ckey, &challenge); err != nil { return fmt.Errorf("datastore.Get error: %v", err) } reg, err := u2f.Register(resp, challenge, &u2f.Config{true}) if err != nil { return fmt.Errorf("u2f.Register error: %v", err) } buf, err := reg.MarshalBinary() if err != nil { return fmt.Errorf("reg.MarshalBinary error: %v", err) } // Save the registration in the datastore regi := Registration{UserIdentity: userIdentity, Counter: 0, U2FRegistrationBytes: buf, Created: time.Now()} // We set the stringKey to 0, because the user identity is not part of the // key. We look up registrations by a datastore query, since there might // be multiple. k := makeKey(ctx, "", "Registration") if _, err := datastore.Put(ctx, k, ®i); err != nil { return fmt.Errorf("datastore.Put error: %v", err) } log.Printf("🍁 Registered: %+v [%+v]", userIdentity, k) return nil }