func()

in lib/cli/cli.go [260:327]


func (h *RegisterHandler) Post(r *http.Request, name string) (proto.Message, error) {
	if name == autoGenerate {
		name = uuid.New()
	}
	email := httputils.QueryParam(r, "email")
	if len(email) == 0 {
		return nil, status.Errorf(codes.InvalidArgument, "missing email address parameter")
	}
	if _, err := mail.ParseAddress(email); err != nil {
		return nil, status.Errorf(codes.InvalidArgument, "invalid email address %q: %v", email, err)
	}
	scope := httputils.QueryParamWithDefault(r, "scope", "openid profile email offline")
	cat := time.Now()
	exp := cat.Add(ttl)
	catProto, err := ptypes.TimestampProto(cat)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "cannot generate iat timestamp: %v", err)
	}
	expProto, err := ptypes.TimestampProto(exp)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "cannot generate exp timestamp: %v", err)
	}
	unique := uuid.New() + "/" + cat.Format(time.RFC3339Nano) + "/" + strconv.FormatUint(rand.Uint64(), 16)
	hash := sha3.Sum256([]byte(unique))
	secret := hex.EncodeToString(hash[:])
	encrypted, err := h.crypt.Encrypt(r.Context(), []byte(secret), "")
	if err != nil {
		return nil, status.Errorf(codes.Internal, "cannot generate secret: %v", err)
	}
	a, err := auth.FromContext(r.Context())
	if err != nil {
		return nil, status.Errorf(codes.Internal, "cannot obtain request context: %v", err)
	}
	u, err := url.Parse(h.authURL)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "invalid redirect URL: %v", err)
	}
	q := u.Query()
	q.Set("grant_type", "authorization_code")
	q.Set("response_type", "code")
	q.Set("client_id", a.ClientID)
	q.Set("scope", scope)
	q.Set("state", name)
	q.Set("redirect_uri", h.accept)
	u.RawQuery = q.Encode()
	h.save = &cpb.CliState{
		Id:              name,
		Email:           email,
		EncryptedSecret: encrypted,
		ClientId:        a.ClientID,
		Scope:           scope,
		AuthUrl:         u.String(),
		CreatedAt:       catProto,
		ExpiresAt:       expProto,
		State:           storage.StateActive,
	}

	// Return the non-encrypted secret whereas `h.save` above will have the secret encrypted.
	return &cpb.CliState{
		Id:        h.save.Id,
		Email:     h.save.Email,
		Secret:    secret,
		Scope:     scope,
		AuthUrl:   strings.Replace(h.cliAuthURL, "{name}", name, -1),
		CreatedAt: catProto,
		ExpiresAt: expProto,
	}, nil
}