mirror of
https://github.com/pomerium/pomerium.git
synced 2025-06-22 04:28:25 +02:00
mcp: client registration/token fixes (#5649)
## Summary Fixes to MCP code registration and token requests. 1. ease some requirements on fields that are RECOMMENDED 2. fill in defaults 3. store both request and response in the client registration 4. check client secret in the /token request ## Related issues - Fixes https://linear.app/pomerium/issue/ENG-2462/mcp-ignore-unknown-grant-types-in-the-client-registration - Fixes https://linear.app/pomerium/issue/ENG-2461/mcp-support-client-secret-in-dynamic-client-registration ## User Explanation <!-- How would you explain this change to the user? If this change doesn't create any user-facing changes, you can leave this blank. If filled out, add the `docs` label --> ## Checklist - [x] reference any related issues - [x] updated unit tests - [x] add appropriate label (`enhancement`, `bug`, `breaking`, `dependencies`, `ci`) - [ ] ready for review
This commit is contained in:
parent
200f2e8164
commit
777b3b12d2
20 changed files with 1440 additions and 461 deletions
|
@ -74,8 +74,8 @@ func (srv *Handler) Authorize(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := oauth21.ValidateAuthorizationRequest(client, v); err != nil {
|
if err := oauth21.ValidateAuthorizationRequest(client.ResponseMetadata, v); err != nil {
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to validate authorization request")
|
log.Ctx(ctx).Error().Err(err).Msg("failed to validate authorization request for a client")
|
||||||
ve := oauth21.Error{Code: oauth21.InvalidRequest}
|
ve := oauth21.Error{Code: oauth21.InvalidRequest}
|
||||||
_ = errors.As(err, &ve)
|
_ = errors.As(err, &ve)
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, ve.Code)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, ve.Code)
|
||||||
|
|
|
@ -119,7 +119,7 @@ func getAuthorizationServerMetadata(host, prefix string) AuthorizationServerMeta
|
||||||
ResponseTypesSupported: []string{"code"},
|
ResponseTypesSupported: []string{"code"},
|
||||||
CodeChallengeMethodsSupported: []string{"S256"},
|
CodeChallengeMethodsSupported: []string{"S256"},
|
||||||
TokenEndpoint: P(path.Join(prefix, tokenEndpoint)),
|
TokenEndpoint: P(path.Join(prefix, tokenEndpoint)),
|
||||||
TokenEndpointAuthMethodsSupported: []string{"none"},
|
TokenEndpointAuthMethodsSupported: []string{"client_secret_basic", "none"},
|
||||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||||
RevocationEndpoint: P(path.Join(prefix, revocationEndpoint)),
|
RevocationEndpoint: P(path.Join(prefix, revocationEndpoint)),
|
||||||
RevocationEndpointAuthMethodsSupported: []string{"client_secret_post"},
|
RevocationEndpointAuthMethodsSupported: []string{"client_secret_post"},
|
||||||
|
|
|
@ -2,15 +2,16 @@ package mcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bufbuild/protovalidate-go"
|
"google.golang.org/protobuf/proto"
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
rfc7591v1 "github.com/pomerium/pomerium/internal/rfc7591"
|
rfc7591v1 "github.com/pomerium/pomerium/internal/rfc7591"
|
||||||
|
"github.com/pomerium/pomerium/pkg/cryptutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxClientRegistrationPayload = 1024 * 1024 // 1MB
|
const maxClientRegistrationPayload = 1024 * 1024 // 1MB
|
||||||
|
@ -34,44 +35,24 @@ func (srv *Handler) RegisterClient(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v := new(rfc7591v1.ClientMetadata)
|
clientRegistration, err := createClientRegistrationFromMetadata(data)
|
||||||
err = protojson.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(data, v)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to unmarshal request body")
|
log.Ctx(ctx).Error().
|
||||||
http.Error(w, "failed to unmarshal request body", http.StatusBadRequest)
|
Str("request", string(data)).
|
||||||
return
|
Err(err).Msg("create client registration")
|
||||||
}
|
|
||||||
|
|
||||||
err = protovalidate.Validate(v)
|
|
||||||
if err != nil {
|
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to validate request body")
|
|
||||||
clientRegistrationBadRequest(w, err)
|
clientRegistrationBadRequest(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := srv.storage.RegisterClient(ctx, v)
|
id, err := srv.storage.RegisterClient(ctx, clientRegistration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to register client")
|
log.Ctx(ctx).Error().Err(err).Msg("failed to register client")
|
||||||
http.Error(w, "failed to register client", http.StatusInternalServerError)
|
http.Error(w, "failed to register client", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := struct {
|
|
||||||
*rfc7591v1.ClientMetadata
|
|
||||||
ClientID string `json:"client_id"`
|
|
||||||
ClientIDIssuedAt int64 `json:"client_id_issued_at"`
|
|
||||||
}{
|
|
||||||
ClientMetadata: v,
|
|
||||||
ClientID: id,
|
|
||||||
ClientIDIssuedAt: time.Now().Unix(),
|
|
||||||
}
|
|
||||||
data, err = json.Marshal(resp)
|
|
||||||
if err != nil {
|
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to marshal response")
|
|
||||||
http.Error(w, "failed to marshal response", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
_, err = w.Write(data)
|
err = rfc7591v1.WriteRegistrationResponse(w, id,
|
||||||
|
clientRegistration.ClientSecret, clientRegistration.ResponseMetadata)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Ctx(ctx).Error().Err(err).Msg("failed to write response")
|
log.Ctx(ctx).Error().Err(err).Msg("failed to write response")
|
||||||
return
|
return
|
||||||
|
@ -93,3 +74,34 @@ func clientRegistrationBadRequest(w http.ResponseWriter, err error) {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
_, _ = w.Write(data)
|
_, _ = w.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createClientRegistrationFromMetadata(
|
||||||
|
requestMetadataText []byte,
|
||||||
|
) (*rfc7591v1.ClientRegistration, error) {
|
||||||
|
requestMetadata, err := rfc7591v1.ParseMetadata(requestMetadataText)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parse: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = requestMetadata.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("validate: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
responseMetadata := proto.CloneOf(requestMetadata)
|
||||||
|
responseMetadata.SetDefaults()
|
||||||
|
|
||||||
|
registration := &rfc7591v1.ClientRegistration{
|
||||||
|
RequestMetadata: requestMetadata,
|
||||||
|
ResponseMetadata: responseMetadata,
|
||||||
|
}
|
||||||
|
|
||||||
|
if requestMetadata.GetTokenEndpointAuthMethod() != rfc7591v1.TokenEndpointAuthMethodNone {
|
||||||
|
registration.ClientSecret = &rfc7591v1.ClientSecret{
|
||||||
|
Value: cryptutil.NewRandomStringN(32),
|
||||||
|
CreatedAt: timestamppb.Now(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return registration, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/log"
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/oauth21"
|
"github.com/pomerium/pomerium/internal/oauth21"
|
||||||
oauth21proto "github.com/pomerium/pomerium/internal/oauth21/gen"
|
oauth21proto "github.com/pomerium/pomerium/internal/oauth21/gen"
|
||||||
|
rfc7591v1 "github.com/pomerium/pomerium/internal/rfc7591"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Token handles the /token endpoint.
|
// Token handles the /token endpoint.
|
||||||
|
@ -21,54 +23,65 @@ func (srv *Handler) Token(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := oauth21.ParseTokenRequest(r)
|
ctx := r.Context()
|
||||||
|
req, err := srv.getTokenRequest(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Ctx(r.Context()).Error().Err(err).Msg("failed to parse token request")
|
log.Ctx(ctx).Error().Err(err).Msg("get token request failed")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidRequest)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch req.GrantType {
|
switch req.GrantType {
|
||||||
case "authorization_code":
|
case "authorization_code":
|
||||||
|
log.Ctx(ctx).Debug().Msg("handling authorization_code token request")
|
||||||
srv.handleAuthorizationCodeToken(w, r, req)
|
srv.handleAuthorizationCodeToken(w, r, req)
|
||||||
default:
|
default:
|
||||||
|
log.Ctx(ctx).Error().Msgf("unsupported grant type: %s", req.GrantType)
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.UnsupportedGrantType)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.UnsupportedGrantType)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.Request, req *oauth21proto.TokenRequest) {
|
func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.Request, tokenReq *oauth21proto.TokenRequest) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
if req.ClientId == nil {
|
if tokenReq.ClientId == nil {
|
||||||
|
log.Ctx(ctx).Error().Msg("missing client_id in token request")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidClient)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidClient)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Code == nil {
|
if tokenReq.Code == nil {
|
||||||
|
log.Ctx(ctx).Error().Msg("missing code in token request")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
code, err := DecryptCode(CodeTypeAuthorization, *req.Code, srv.cipher, *req.ClientId, time.Now())
|
code, err := DecryptCode(CodeTypeAuthorization, *tokenReq.Code, srv.cipher, *tokenReq.ClientId, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to decrypt authorization code")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
authReq, err := srv.storage.GetAuthorizationRequest(ctx, code.Id)
|
authReq, err := srv.storage.GetAuthorizationRequest(ctx, code.Id)
|
||||||
if status.Code(err) == codes.NotFound {
|
if status.Code(err) == codes.NotFound {
|
||||||
|
log.Ctx(ctx).Error().Msg("authorization request not found")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to get authorization request and client")
|
||||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
if *req.ClientId != authReq.ClientId {
|
if *tokenReq.ClientId != authReq.ClientId {
|
||||||
|
log.Ctx(ctx).Error().Msgf("client ID mismatch: %s != %s", *tokenReq.ClientId, authReq.ClientId)
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = CheckPKCE(authReq.GetCodeChallengeMethod(), authReq.GetCodeChallenge(), req.GetCodeVerifier())
|
err = CheckPKCE(authReq.GetCodeChallengeMethod(), authReq.GetCodeChallenge(), tokenReq.GetCodeVerifier())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to check PKCE")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -77,24 +90,28 @@ func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.
|
||||||
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-4.1.3
|
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-12#section-4.1.3
|
||||||
err = srv.storage.DeleteAuthorizationRequest(ctx, code.Id)
|
err = srv.storage.DeleteAuthorizationRequest(ctx, code.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to delete authorization request")
|
||||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
session, err := srv.storage.GetSession(ctx, authReq.SessionId)
|
session, err := srv.storage.GetSession(ctx, authReq.SessionId)
|
||||||
if status.Code(err) == codes.NotFound {
|
if status.Code(err) == codes.NotFound {
|
||||||
|
log.Ctx(ctx).Error().Msg("session not found")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, err := srv.GetAccessTokenForSession(session.Id, session.ExpiresAt.AsTime())
|
accessToken, err := srv.GetAccessTokenForSession(session.Id, session.ExpiresAt.AsTime())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to get access token for session")
|
||||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
expiresIn := time.Until(session.ExpiresAt.AsTime())
|
expiresIn := time.Until(session.ExpiresAt.AsTime())
|
||||||
if expiresIn < 0 {
|
if expiresIn < 0 {
|
||||||
|
log.Ctx(ctx).Error().Msg("session has already expired")
|
||||||
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
oauth21.ErrorResponse(w, http.StatusBadRequest, oauth21.InvalidGrant)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -107,6 +124,7 @@ func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.
|
||||||
|
|
||||||
data, err := json.Marshal(resp) // not using protojson.Marshal here because it emits numbers as strings, which is valid, but for some reason Node.js / mcp typescript SDK doesn't like it
|
data, err := json.Marshal(resp) // not using protojson.Marshal here because it emits numbers as strings, which is valid, but for some reason Node.js / mcp typescript SDK doesn't like it
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
log.Ctx(ctx).Error().Err(err).Msg("failed to marshal token response")
|
||||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -116,3 +134,46 @@ func (srv *Handler) handleAuthorizationCodeToken(w http.ResponseWriter, r *http.
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
_, _ = w.Write(data)
|
_, _ = w.Write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (srv *Handler) getTokenRequest(
|
||||||
|
r *http.Request,
|
||||||
|
) (*oauth21proto.TokenRequest, error) {
|
||||||
|
tokenReq, err := oauth21.ParseTokenRequest(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to parse token request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := r.Context()
|
||||||
|
clientReg, err := srv.storage.GetClient(ctx, tokenReq.GetClientId())
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get client registration: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m := clientReg.ResponseMetadata.GetTokenEndpointAuthMethod()
|
||||||
|
if m == rfc7591v1.TokenEndpointAuthMethodNone {
|
||||||
|
return tokenReq, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
secret := clientReg.ClientSecret
|
||||||
|
if secret == nil {
|
||||||
|
return nil, fmt.Errorf("client registration does not have a client secret")
|
||||||
|
}
|
||||||
|
if expires := secret.ExpiresAt; expires != nil && expires.AsTime().Before(time.Now()) {
|
||||||
|
return nil, fmt.Errorf("client registration client secret has expired")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch m {
|
||||||
|
case rfc7591v1.TokenEndpointAuthMethodClientSecretBasic:
|
||||||
|
case rfc7591v1.TokenEndpointAuthMethodClientSecretPost:
|
||||||
|
if tokenReq.ClientSecret == nil {
|
||||||
|
return nil, fmt.Errorf("client_secret was not provided")
|
||||||
|
}
|
||||||
|
if tokenReq.GetClientSecret() != secret.Value {
|
||||||
|
return nil, fmt.Errorf("client secret mismatch")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupported token endpoint authentication method: %s", m)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tokenReq, nil
|
||||||
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func NewStorage(
|
||||||
|
|
||||||
func (storage *Storage) RegisterClient(
|
func (storage *Storage) RegisterClient(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *rfc7591v1.ClientMetadata,
|
req *rfc7591v1.ClientRegistration,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
data := protoutil.NewAny(req)
|
data := protoutil.NewAny(req)
|
||||||
id := uuid.NewString()
|
id := uuid.NewString()
|
||||||
|
@ -51,8 +51,8 @@ func (storage *Storage) RegisterClient(
|
||||||
func (storage *Storage) GetClient(
|
func (storage *Storage) GetClient(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
id string,
|
id string,
|
||||||
) (*rfc7591v1.ClientMetadata, error) {
|
) (*rfc7591v1.ClientRegistration, error) {
|
||||||
v := new(rfc7591v1.ClientMetadata)
|
v := new(rfc7591v1.ClientRegistration)
|
||||||
rec, err := storage.client.Get(ctx, &databroker.GetRequest{
|
rec, err := storage.client.Get(ctx, &databroker.GetRequest{
|
||||||
Type: protoutil.GetTypeURL(v),
|
Type: protoutil.GetTypeURL(v),
|
||||||
Id: id,
|
Id: id,
|
||||||
|
|
|
@ -62,7 +62,7 @@ func TestStorage(t *testing.T) {
|
||||||
t.Run("client registration", func(t *testing.T) {
|
t.Run("client registration", func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
id, err := storage.RegisterClient(ctx, &rfc7591v1.ClientMetadata{})
|
id, err := storage.RegisterClient(ctx, &rfc7591v1.ClientRegistration{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotEmpty(t, id)
|
require.NotEmpty(t, id)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ func ParseCodeGrantAuthorizeRequest(r *http.Request) (*gen.AuthorizationRequest,
|
||||||
RedirectUri: optionalFormParam(r, "redirect_uri"),
|
RedirectUri: optionalFormParam(r, "redirect_uri"),
|
||||||
ResponseType: r.Form.Get("response_type"),
|
ResponseType: r.Form.Get("response_type"),
|
||||||
State: optionalFormParam(r, "state"),
|
State: optionalFormParam(r, "state"),
|
||||||
CodeChallenge: r.Form.Get("code_challenge"),
|
CodeChallenge: optionalFormParam(r, "code_challenge"),
|
||||||
CodeChallengeMethod: optionalFormParam(r, "code_challenge_method"),
|
CodeChallengeMethod: optionalFormParam(r, "code_challenge_method"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
version: v2
|
version: v2
|
||||||
deps:
|
deps:
|
||||||
- name: buf.build/bufbuild/protovalidate
|
- name: buf.build/bufbuild/protovalidate
|
||||||
commit: 8976f5be98c146529b1cc15cd2012b60
|
commit: b52ab10f44684cb19d1fbcad56aedd36
|
||||||
digest: b5:5d513af91a439d9e78cacac0c9455c7cb885a8737d30405d0b91974fe05276d19c07a876a51a107213a3d01b83ecc912996cdad4cddf7231f91379079cf7488d
|
digest: b5:5f464399f5ea7546eb3c6a4e822a306da538298f3d87e9f974f4523d4955de396eb2b8b52a2f3f06ac290764d80cecbaa0a4c96560558e43d9b1c722e61a9d5c
|
||||||
|
|
|
@ -43,8 +43,9 @@ type AuthorizationRequest struct {
|
||||||
State *string `protobuf:"bytes,4,opt,name=state,proto3,oneof" json:"state,omitempty"`
|
State *string `protobuf:"bytes,4,opt,name=state,proto3,oneof" json:"state,omitempty"`
|
||||||
// OPTIONAL. The scope of the access request as described by Section 1.4.1.
|
// OPTIONAL. The scope of the access request as described by Section 1.4.1.
|
||||||
Scopes []string `protobuf:"bytes,5,rep,name=scopes,proto3" json:"scopes,omitempty"`
|
Scopes []string `protobuf:"bytes,5,rep,name=scopes,proto3" json:"scopes,omitempty"`
|
||||||
// REQUIRED, assumes https://www.rfc-editor.org/rfc/rfc7636.html#section-4.1
|
// REQUIRED or RECOMMENDED, assumes https://www.rfc-editor.org/rfc/rfc7636.html#section-4.1
|
||||||
CodeChallenge string `protobuf:"bytes,6,opt,name=code_challenge,json=codeChallenge,proto3" json:"code_challenge,omitempty"`
|
// subject to whether the client is public or confidential.
|
||||||
|
CodeChallenge *string `protobuf:"bytes,6,opt,name=code_challenge,json=codeChallenge,proto3,oneof" json:"code_challenge,omitempty"`
|
||||||
// OPTIONAL, defaults to plain if not present in the request. Code verifier
|
// OPTIONAL, defaults to plain if not present in the request. Code verifier
|
||||||
// transformation method is S256 or plain.
|
// transformation method is S256 or plain.
|
||||||
CodeChallengeMethod *string `protobuf:"bytes,7,opt,name=code_challenge_method,json=codeChallengeMethod,proto3,oneof" json:"code_challenge_method,omitempty"`
|
CodeChallengeMethod *string `protobuf:"bytes,7,opt,name=code_challenge_method,json=codeChallengeMethod,proto3,oneof" json:"code_challenge_method,omitempty"`
|
||||||
|
@ -124,8 +125,8 @@ func (x *AuthorizationRequest) GetScopes() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AuthorizationRequest) GetCodeChallenge() string {
|
func (x *AuthorizationRequest) GetCodeChallenge() string {
|
||||||
if x != nil {
|
if x != nil && x.CodeChallenge != nil {
|
||||||
return x.CodeChallenge
|
return *x.CodeChallenge
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -158,7 +159,7 @@ var file_authorization_request_proto_rawDesc = string([]byte{
|
||||||
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6f,
|
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6f,
|
||||||
0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69,
|
||||||
0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
|
0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0xcb, 0x03, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
|
0x6f, 0x74, 0x6f, 0x22, 0xe0, 0x03, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x09,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x09,
|
||||||
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||||
0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
|
0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49,
|
||||||
|
@ -171,33 +172,34 @@ var file_authorization_request_proto_rawDesc = string([]byte{
|
||||||
0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52,
|
0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52,
|
||||||
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f,
|
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x6f,
|
||||||
0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||||
0x73, 0x12, 0x34, 0x0a, 0x0e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65,
|
0x73, 0x12, 0x36, 0x0a, 0x0e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65,
|
||||||
0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, 0xba, 0x48, 0x0a, 0xc8, 0x01,
|
0x6e, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05,
|
||||||
0x01, 0x72, 0x05, 0x10, 0x2b, 0x18, 0x80, 0x01, 0x52, 0x0d, 0x63, 0x6f, 0x64, 0x65, 0x43, 0x68,
|
0x10, 0x2b, 0x18, 0x80, 0x01, 0x48, 0x02, 0x52, 0x0d, 0x63, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61,
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x12, 0x4b, 0x0a, 0x15, 0x63, 0x6f, 0x64, 0x65, 0x5f,
|
0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x88, 0x01, 0x01, 0x12, 0x4b, 0x0a, 0x15, 0x63, 0x6f, 0x64,
|
||||||
0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64,
|
0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68,
|
||||||
0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0xba, 0x48, 0x0f, 0x72, 0x0d, 0x52, 0x04, 0x53,
|
0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x12, 0xba, 0x48, 0x0f, 0x72, 0x0d, 0x52,
|
||||||
0x32, 0x35, 0x36, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x48, 0x02, 0x52, 0x13, 0x63, 0x6f,
|
0x04, 0x53, 0x32, 0x35, 0x36, 0x52, 0x05, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x48, 0x03, 0x52, 0x13,
|
||||||
0x64, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f,
|
0x63, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x4d, 0x65, 0x74,
|
||||||
0x64, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f,
|
0x68, 0x6f, 0x64, 0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
||||||
0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01,
|
0x6e, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
|
||||||
0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x07, 0x75,
|
0x01, 0x01, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, 0x0a,
|
||||||
0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48,
|
0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06,
|
||||||
0x03, 0xc8, 0x01, 0x01, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x42, 0x0f, 0x0a, 0x0d,
|
0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x42, 0x0f,
|
||||||
0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x08, 0x0a,
|
0x0a, 0x0d, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x42,
|
||||||
0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x63, 0x6f, 0x64, 0x65,
|
0x08, 0x0a, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x63, 0x6f,
|
||||||
0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f,
|
0x64, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x42, 0x18, 0x0a, 0x16,
|
||||||
0x64, 0x42, 0x97, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32,
|
0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f,
|
||||||
0x31, 0x42, 0x19, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x97, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x6f,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31,
|
0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x42, 0x19, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a,
|
||||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x74,
|
||||||
0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x69, 0x6e, 0x74,
|
0x6f, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x2f, 0x67, 0x65,
|
0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75,
|
||||||
0x6e, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32,
|
0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x6f, 0x61, 0x75, 0x74, 0x68,
|
||||||
0x31, 0xca, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0xe2, 0x02, 0x13, 0x4f, 0x61,
|
0x32, 0x31, 0x2f, 0x67, 0x65, 0x6e, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x4f,
|
||||||
0x75, 0x74, 0x68, 0x32, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0xca, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31,
|
||||||
0x61, 0xea, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
0xe2, 0x02, 0x13, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
|
||||||
0x74, 0x6f, 0x33,
|
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x32, 0x31,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
})
|
})
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -34,10 +34,10 @@ message AuthorizationRequest {
|
||||||
// OPTIONAL. The scope of the access request as described by Section 1.4.1.
|
// OPTIONAL. The scope of the access request as described by Section 1.4.1.
|
||||||
repeated string scopes = 5;
|
repeated string scopes = 5;
|
||||||
|
|
||||||
// REQUIRED, assumes https://www.rfc-editor.org/rfc/rfc7636.html#section-4.1
|
// REQUIRED or RECOMMENDED, assumes https://www.rfc-editor.org/rfc/rfc7636.html#section-4.1
|
||||||
string code_challenge = 6 [
|
// subject to whether the client is public or confidential.
|
||||||
(buf.validate.field).required = true,
|
optional string code_challenge = 6 [
|
||||||
(buf.validate.field).string = {min_len: 43, max_len: 128}
|
(buf.validate.field).string = {min_len: 43, max_len: 128}
|
||||||
];
|
];
|
||||||
|
|
||||||
// OPTIONAL, defaults to plain if not present in the request. Code verifier
|
// OPTIONAL, defaults to plain if not present in the request. Code verifier
|
||||||
|
|
|
@ -15,6 +15,9 @@ func ParseTokenRequest(r *http.Request) (*gen.TokenRequest, error) {
|
||||||
return nil, fmt.Errorf("failed to parse form: %w", err)
|
return nil, fmt.Errorf("failed to parse form: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extract client credentials from HTTP Basic Authorization header, if present
|
||||||
|
basicID, basicSecret, basicOK := r.BasicAuth()
|
||||||
|
|
||||||
v := &gen.TokenRequest{
|
v := &gen.TokenRequest{
|
||||||
GrantType: r.Form.Get("grant_type"),
|
GrantType: r.Form.Get("grant_type"),
|
||||||
Code: optionalFormParam(r, "code"),
|
Code: optionalFormParam(r, "code"),
|
||||||
|
@ -25,6 +28,15 @@ func ParseTokenRequest(r *http.Request) (*gen.TokenRequest, error) {
|
||||||
ClientSecret: optionalFormParam(r, "client_secret"),
|
ClientSecret: optionalFormParam(r, "client_secret"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if basicOK {
|
||||||
|
if v.ClientId == nil && basicID != "" {
|
||||||
|
v.ClientId = &basicID
|
||||||
|
}
|
||||||
|
if v.ClientSecret == nil && basicSecret != "" {
|
||||||
|
v.ClientSecret = &basicSecret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = protovalidate.Validate(v)
|
err = protovalidate.Validate(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to validate token request: %w", err)
|
return nil, fmt.Errorf("failed to validate token request: %w", err)
|
||||||
|
|
48
internal/oauth21/token_test.go
Normal file
48
internal/oauth21/token_test.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package oauth21_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/pomerium/pomerium/internal/oauth21"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseTokenRequest_BasicAuth(t *testing.T) {
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("grant_type", "authorization_code")
|
||||||
|
form.Set("code", "abc")
|
||||||
|
req, err := http.NewRequest(http.MethodPost, "/token", strings.NewReader(form.Encode()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.SetBasicAuth("myclient", "secret")
|
||||||
|
|
||||||
|
tr, err := oauth21.ParseTokenRequest(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, tr.ClientId)
|
||||||
|
require.Equal(t, "myclient", *tr.ClientId)
|
||||||
|
require.NotNil(t, tr.ClientSecret)
|
||||||
|
require.Equal(t, "secret", *tr.ClientSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseTokenRequest_BasicAuthWithBodyOverride(t *testing.T) {
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("grant_type", "authorization_code")
|
||||||
|
form.Set("code", "abc")
|
||||||
|
form.Set("client_id", "bodyid")
|
||||||
|
form.Set("client_secret", "bodysecret")
|
||||||
|
req, err := http.NewRequest(http.MethodPost, "/token", strings.NewReader(form.Encode()))
|
||||||
|
require.NoError(t, err)
|
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
req.SetBasicAuth("basicid", "basicsecret")
|
||||||
|
|
||||||
|
tr, err := oauth21.ParseTokenRequest(req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, tr.ClientId)
|
||||||
|
require.Equal(t, "bodyid", *tr.ClientId) // body should win
|
||||||
|
require.NotNil(t, tr.ClientSecret)
|
||||||
|
require.Equal(t, "bodysecret", *tr.ClientSecret)
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package oauth21
|
package oauth21
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"github.com/pomerium/pomerium/internal/oauth21/gen"
|
"github.com/pomerium/pomerium/internal/oauth21/gen"
|
||||||
|
@ -8,17 +9,45 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func ValidateAuthorizationRequest(
|
func ValidateAuthorizationRequest(
|
||||||
client *rfc7591v1.ClientMetadata,
|
client *rfc7591v1.Metadata,
|
||||||
req *gen.AuthorizationRequest,
|
req *gen.AuthorizationRequest,
|
||||||
) error {
|
) error {
|
||||||
if err := ValidateAuthorizationRequestRedirectURI(client, req.RedirectUri); err != nil {
|
if err := ValidateAuthorizationRequestRedirectURI(client, req.RedirectUri); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := ValidateAuthorizationRequestCodeChallenge(client, req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateAuthorizationRequestCodeChallenge(
|
||||||
|
client *rfc7591v1.Metadata,
|
||||||
|
req *gen.AuthorizationRequest,
|
||||||
|
) error {
|
||||||
|
m := client.GetTokenEndpointAuthMethod()
|
||||||
|
switch m {
|
||||||
|
case rfc7591v1.TokenEndpointAuthMethodNone:
|
||||||
|
if req.GetCodeChallenge() == "" {
|
||||||
|
return Error{
|
||||||
|
Code: InvalidRequest,
|
||||||
|
Description: "code challenge are required when token endpoint auth method is 'none'",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case rfc7591v1.TokenEndpointAuthMethodClientSecretBasic,
|
||||||
|
rfc7591v1.TokenEndpointAuthMethodClientSecretPost:
|
||||||
|
// code challenge is recommended but not required for these methods
|
||||||
|
default:
|
||||||
|
return Error{
|
||||||
|
Code: InvalidRequest,
|
||||||
|
Description: fmt.Sprintf("unsupported token endpoint auth method: %s", m),
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateAuthorizationRequestRedirectURI(
|
func ValidateAuthorizationRequestRedirectURI(
|
||||||
client *rfc7591v1.ClientMetadata,
|
client *rfc7591v1.Metadata,
|
||||||
redirectURI *string,
|
redirectURI *string,
|
||||||
) error {
|
) error {
|
||||||
if len(client.RedirectUris) == 0 {
|
if len(client.RedirectUris) == 0 {
|
||||||
|
|
|
@ -13,17 +13,67 @@ import (
|
||||||
|
|
||||||
func TestValidateRequest(t *testing.T) {
|
func TestValidateRequest(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
clientBasic := rfc7591v1.TokenEndpointAuthMethodClientSecretBasic
|
||||||
|
clientNone := rfc7591v1.TokenEndpointAuthMethodNone
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
name string
|
name string
|
||||||
client *rfc7591v1.ClientMetadata
|
client *rfc7591v1.Metadata
|
||||||
req *gen.AuthorizationRequest
|
req *gen.AuthorizationRequest
|
||||||
err bool
|
err bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"optional redirect_uri, multiple redirect_uris",
|
"default token auth method, no code challenge",
|
||||||
&rfc7591v1.ClientMetadata{
|
&rfc7591v1.Metadata{
|
||||||
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
},
|
},
|
||||||
|
&gen.AuthorizationRequest{
|
||||||
|
RedirectUri: proto.String("https://example.com/callback"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"none token auth method, no code challenge",
|
||||||
|
&rfc7591v1.Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientNone,
|
||||||
|
},
|
||||||
|
&gen.AuthorizationRequest{
|
||||||
|
RedirectUri: proto.String("https://example.com/callback"),
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"none token auth method, code challenge is provided",
|
||||||
|
&rfc7591v1.Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientNone,
|
||||||
|
},
|
||||||
|
&gen.AuthorizationRequest{
|
||||||
|
RedirectUri: proto.String("https://example.com/callback"),
|
||||||
|
CodeChallenge: proto.String("challenge"),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"none token auth method, code challenge and method are provided",
|
||||||
|
&rfc7591v1.Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientNone,
|
||||||
|
},
|
||||||
|
&gen.AuthorizationRequest{
|
||||||
|
RedirectUri: proto.String("https://example.com/callback"),
|
||||||
|
CodeChallenge: proto.String("challenge"),
|
||||||
|
CodeChallengeMethod: proto.String("S256"),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"optional redirect_uri, multiple redirect_uris",
|
||||||
|
&rfc7591v1.Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientBasic,
|
||||||
|
},
|
||||||
&gen.AuthorizationRequest{
|
&gen.AuthorizationRequest{
|
||||||
RedirectUri: nil,
|
RedirectUri: nil,
|
||||||
},
|
},
|
||||||
|
@ -31,8 +81,9 @@ func TestValidateRequest(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"optional redirect_uri, single redirect_uri",
|
"optional redirect_uri, single redirect_uri",
|
||||||
&rfc7591v1.ClientMetadata{
|
&rfc7591v1.Metadata{
|
||||||
RedirectUris: []string{"https://example.com/callback"},
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientBasic,
|
||||||
},
|
},
|
||||||
&gen.AuthorizationRequest{
|
&gen.AuthorizationRequest{
|
||||||
RedirectUri: nil,
|
RedirectUri: nil,
|
||||||
|
@ -41,8 +92,9 @@ func TestValidateRequest(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matching redirect_uri",
|
"matching redirect_uri",
|
||||||
&rfc7591v1.ClientMetadata{
|
&rfc7591v1.Metadata{
|
||||||
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientBasic,
|
||||||
},
|
},
|
||||||
&gen.AuthorizationRequest{
|
&gen.AuthorizationRequest{
|
||||||
RedirectUri: proto.String("https://example.com/callback"),
|
RedirectUri: proto.String("https://example.com/callback"),
|
||||||
|
@ -51,8 +103,9 @@ func TestValidateRequest(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"non-matching redirect_uri",
|
"non-matching redirect_uri",
|
||||||
&rfc7591v1.ClientMetadata{
|
&rfc7591v1.Metadata{
|
||||||
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/other-callback"},
|
||||||
|
TokenEndpointAuthMethod: &clientBasic,
|
||||||
},
|
},
|
||||||
&gen.AuthorizationRequest{
|
&gen.AuthorizationRequest{
|
||||||
RedirectUri: proto.String("https://example.com/invalid-callback"),
|
RedirectUri: proto.String("https://example.com/invalid-callback"),
|
||||||
|
|
|
@ -2,5 +2,5 @@
|
||||||
version: v2
|
version: v2
|
||||||
deps:
|
deps:
|
||||||
- name: buf.build/bufbuild/protovalidate
|
- name: buf.build/bufbuild/protovalidate
|
||||||
commit: 7712fb530c574b95bc1d57c0877543c3
|
commit: b52ab10f44684cb19d1fbcad56aedd36
|
||||||
digest: b5:b3e9c9428384357e3b73e4d5a4614328b0a4b1595b10163bbe9483fa16204749274c41797bd49b0d716479c855aa35c1172a94f471fa120ba8369637fd138829
|
digest: b5:5f464399f5ea7546eb3c6a4e822a306da538298f3d87e9f974f4523d4955de396eb2b8b52a2f3f06ac290764d80cecbaa0a4c96560558e43d9b1c722e61a9d5c
|
||||||
|
|
103
internal/rfc7591/format.go
Normal file
103
internal/rfc7591/format.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package rfc7591v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/bufbuild/protovalidate-go"
|
||||||
|
"google.golang.org/protobuf/encoding/protojson"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
TokenEndpointAuthMethodNone = "none"
|
||||||
|
TokenEndpointAuthMethodClientSecretBasic = "client_secret_basic"
|
||||||
|
TokenEndpointAuthMethodClientSecretPost = "client_secret_post"
|
||||||
|
|
||||||
|
GrantTypesAuthorizationCode = "authorization_code"
|
||||||
|
GrantTypesImplicit = "implicit"
|
||||||
|
GrantTypesPassword = "password"
|
||||||
|
GrantTypesClientCredentials = "client_credentials"
|
||||||
|
GrantTypesRefreshToken = "refresh_token"
|
||||||
|
GrantTypesJWTBearer = "urn:ietf:params:oauth:grant-type:jwt-bearer" //nolint:gosec
|
||||||
|
GrantTypesSAML2Bearer = "urn:ietf:params:oauth:grant-type:saml2-bearer" //nolint:gosec
|
||||||
|
GrantTypesDeviceCode = "urn:ietf:params:oauth:grant-type:device_code" //nolint:gosec
|
||||||
|
|
||||||
|
ResponseTypesCode = "code"
|
||||||
|
ResponseTypeToken = "token"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *Metadata) SetDefaults() {
|
||||||
|
if v.TokenEndpointAuthMethod == nil {
|
||||||
|
v.TokenEndpointAuthMethod = proto.String(TokenEndpointAuthMethodClientSecretBasic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.GrantTypes) == 0 {
|
||||||
|
v.GrantTypes = []string{GrantTypesAuthorizationCode}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v.ResponseTypes) == 0 {
|
||||||
|
v.ResponseTypes = []string{ResponseTypesCode}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Metadata) Validate() error {
|
||||||
|
return protovalidate.Validate(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseMetadata(
|
||||||
|
data []byte,
|
||||||
|
) (*Metadata, error) {
|
||||||
|
v := new(Metadata)
|
||||||
|
err := protojson.UnmarshalOptions{
|
||||||
|
AllowPartial: false,
|
||||||
|
DiscardUnknown: true,
|
||||||
|
}.Unmarshal(data, v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteRegistrationResponse(
|
||||||
|
w io.Writer,
|
||||||
|
clientID string,
|
||||||
|
clientSecret *ClientSecret,
|
||||||
|
metadata *Metadata,
|
||||||
|
) error {
|
||||||
|
var metadataJSON map[string]any
|
||||||
|
if metadata == nil {
|
||||||
|
return fmt.Errorf("metadata cannot be nil")
|
||||||
|
}
|
||||||
|
metadataBytes, err := protojson.MarshalOptions{
|
||||||
|
UseProtoNames: true,
|
||||||
|
EmitUnpopulated: false,
|
||||||
|
}.Marshal(metadata)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(metadataBytes, &metadataJSON); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataJSON["client_id"] = clientID
|
||||||
|
|
||||||
|
if clientSecret != nil {
|
||||||
|
metadataJSON["client_secret"] = clientSecret.Value
|
||||||
|
if clientSecret.CreatedAt != nil {
|
||||||
|
metadataJSON["client_id_issued_at"] = clientSecret.CreatedAt.Seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per RFC 7591: client_secret_expires_at is REQUIRED if client_secret is issued
|
||||||
|
// Value should be 0 if the secret doesn't expire
|
||||||
|
if clientSecret.ExpiresAt != nil {
|
||||||
|
metadataJSON["client_secret_expires_at"] = clientSecret.ExpiresAt.Seconds
|
||||||
|
} else {
|
||||||
|
metadataJSON["client_secret_expires_at"] = int64(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.NewEncoder(w).Encode(metadataJSON)
|
||||||
|
}
|
540
internal/rfc7591/format_test.go
Normal file
540
internal/rfc7591/format_test.go
Normal file
|
@ -0,0 +1,540 @@
|
||||||
|
package rfc7591v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
"google.golang.org/protobuf/testing/protocmp"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseMetadata(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
want *Metadata
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "minimal valid metadata",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"]
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretBasic),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "full metadata with all fields",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback", "https://example.com/callback2"],
|
||||||
|
"token_endpoint_auth_method": "client_secret_post",
|
||||||
|
"grant_types": ["authorization_code", "refresh_token"],
|
||||||
|
"response_types": ["code"],
|
||||||
|
"client_name": "Test Client",
|
||||||
|
"client_name_localized": {"en": "Test Client", "es": "Cliente de Prueba"},
|
||||||
|
"client_uri": "https://example.com",
|
||||||
|
"client_uri_localized": {"en": "https://example.com/en"},
|
||||||
|
"logo_uri": "https://example.com/logo.png",
|
||||||
|
"scope": "openid profile email",
|
||||||
|
"contacts": ["admin@example.com", "support@example.com"],
|
||||||
|
"tos_uri": "https://example.com/tos",
|
||||||
|
"policy_uri": "https://example.com/privacy",
|
||||||
|
"jwks_uri": "https://example.com/.well-known/jwks.json",
|
||||||
|
"software_id": "test-client-v1",
|
||||||
|
"software_version": "1.0.0"
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback", "https://example.com/callback2"},
|
||||||
|
TokenEndpointAuthMethod: proto.String("client_secret_post"),
|
||||||
|
GrantTypes: []string{"authorization_code", "refresh_token"},
|
||||||
|
ResponseTypes: []string{"code"},
|
||||||
|
ClientName: proto.String("Test Client"),
|
||||||
|
ClientNameLocalized: map[string]string{
|
||||||
|
"en": "Test Client",
|
||||||
|
"es": "Cliente de Prueba",
|
||||||
|
},
|
||||||
|
ClientUri: proto.String("https://example.com"),
|
||||||
|
ClientUriLocalized: map[string]string{
|
||||||
|
"en": "https://example.com/en",
|
||||||
|
},
|
||||||
|
LogoUri: proto.String("https://example.com/logo.png"),
|
||||||
|
Scope: proto.String("openid profile email"),
|
||||||
|
Contacts: []string{"admin@example.com", "support@example.com"},
|
||||||
|
TosUri: proto.String("https://example.com/tos"),
|
||||||
|
PolicyUri: proto.String("https://example.com/privacy"),
|
||||||
|
JwksUri: proto.String("https://example.com/.well-known/jwks.json"),
|
||||||
|
SoftwareId: proto.String("test-client-v1"),
|
||||||
|
SoftwareVersion: proto.String("1.0.0"),
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "metadata with jwks instead of jwks_uri",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"jwks": {
|
||||||
|
"keys": [{
|
||||||
|
"kty": "RSA",
|
||||||
|
"rsa_params": {
|
||||||
|
"n": "example-modulus",
|
||||||
|
"e": "AQAB"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretBasic),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
Jwks: &JsonWebKeySet{
|
||||||
|
Keys: []*JsonWebKey{{
|
||||||
|
Kty: "RSA",
|
||||||
|
KeyTypeParameters: &JsonWebKey_RsaParams{
|
||||||
|
RsaParams: &RsaKeyParameters{
|
||||||
|
N: "example-modulus",
|
||||||
|
E: "AQAB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "explicit token_endpoint_auth_method none",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"token_endpoint_auth_method": "none"
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String("none"),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "custom grant and response types",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"grant_types": ["implicit", "client_credentials"],
|
||||||
|
"response_types": ["token", "code"]
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretBasic),
|
||||||
|
GrantTypes: []string{"implicit", "client_credentials"},
|
||||||
|
ResponseTypes: []string{"token", "code"},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty input",
|
||||||
|
input: "",
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid JSON",
|
||||||
|
input: `{"redirect_uris": [}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "missing required redirect_uris",
|
||||||
|
input: `{
|
||||||
|
"client_name": "Test Client"
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty redirect_uris array",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": []
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid redirect_uri",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["not-a-uri"]
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid token_endpoint_auth_method",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"token_endpoint_auth_method": "invalid_method"
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid email in contacts",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"contacts": ["not-an-email"]
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid scope format",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"scope": " invalid spaces "
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both jwks and jwks_uri provided",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"jwks_uri": "https://example.com/.well-known/jwks.json",
|
||||||
|
"jwks": {
|
||||||
|
"keys": [{
|
||||||
|
"kty": "RSA",
|
||||||
|
"rsa_params": {
|
||||||
|
"n": "example-modulus",
|
||||||
|
"e": "AQAB"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "client_name too long",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"client_name": "` + strings.Repeat("a", 256) + `"
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "discard unknown fields",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"unknown_field": "should be ignored",
|
||||||
|
"another_unknown": 123
|
||||||
|
}`,
|
||||||
|
want: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretBasic),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid BCP 47 language tag - segment too long",
|
||||||
|
input: `{
|
||||||
|
"redirect_uris": ["https://example.com/callback"],
|
||||||
|
"client_name_localized": {"toolongtagsegment": "Test Client"}
|
||||||
|
}`,
|
||||||
|
wantErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ParseMetadata([]byte(tt.input))
|
||||||
|
if err == nil && got != nil {
|
||||||
|
got.SetDefaults()
|
||||||
|
err = got.Validate()
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got nil")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if diff := cmp.Diff(tt.want, got, protocmp.Transform()); diff != "" {
|
||||||
|
t.Errorf("ParseMetadata() mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteRegistrationResponse(t *testing.T) {
|
||||||
|
// Test timestamp for consistent testing
|
||||||
|
testTime := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
||||||
|
testTimestamp := timestamppb.New(testTime)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
clientID string
|
||||||
|
clientSecret *ClientSecret
|
||||||
|
metadata *Metadata
|
||||||
|
want map[string]any
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "minimal response without client secret",
|
||||||
|
clientID: "test-client-123",
|
||||||
|
metadata: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodNone),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
want: map[string]any{
|
||||||
|
"client_id": "test-client-123",
|
||||||
|
"redirect_uris": []any{"https://example.com/callback"},
|
||||||
|
"token_endpoint_auth_method": TokenEndpointAuthMethodNone,
|
||||||
|
"grant_types": []any{GrantTypesAuthorizationCode},
|
||||||
|
"response_types": []any{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "response with client secret and timestamps",
|
||||||
|
clientID: "test-client-456",
|
||||||
|
clientSecret: &ClientSecret{
|
||||||
|
Value: "super-secret-value",
|
||||||
|
CreatedAt: testTimestamp,
|
||||||
|
ExpiresAt: timestamppb.New(testTime.Add(24 * time.Hour)),
|
||||||
|
},
|
||||||
|
metadata: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretPost),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode, GrantTypesRefreshToken},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
ClientName: proto.String("Test Client"),
|
||||||
|
Scope: proto.String("openid profile email"),
|
||||||
|
},
|
||||||
|
want: map[string]any{
|
||||||
|
"client_id": "test-client-456",
|
||||||
|
"client_secret": "super-secret-value",
|
||||||
|
"client_id_issued_at": float64(testTime.Unix()),
|
||||||
|
"client_secret_expires_at": float64(testTime.Add(24 * time.Hour).Unix()),
|
||||||
|
"redirect_uris": []any{"https://example.com/callback"},
|
||||||
|
"token_endpoint_auth_method": TokenEndpointAuthMethodClientSecretPost,
|
||||||
|
"grant_types": []any{GrantTypesAuthorizationCode, GrantTypesRefreshToken},
|
||||||
|
"response_types": []any{ResponseTypesCode},
|
||||||
|
"client_name": "Test Client",
|
||||||
|
"scope": "openid profile email",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "response with client secret but no timestamps",
|
||||||
|
clientID: "test-client-789",
|
||||||
|
clientSecret: &ClientSecret{
|
||||||
|
Value: "another-secret",
|
||||||
|
// CreatedAt and ExpiresAt are nil
|
||||||
|
},
|
||||||
|
metadata: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretBasic),
|
||||||
|
GrantTypes: []string{GrantTypesClientCredentials},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
want: map[string]any{
|
||||||
|
"client_id": "test-client-789",
|
||||||
|
"client_secret": "another-secret",
|
||||||
|
"client_secret_expires_at": float64(0), // Required per RFC when client_secret is present
|
||||||
|
"redirect_uris": []any{"https://example.com/callback"},
|
||||||
|
"token_endpoint_auth_method": TokenEndpointAuthMethodClientSecretBasic,
|
||||||
|
"grant_types": []any{GrantTypesClientCredentials},
|
||||||
|
"response_types": []any{ResponseTypesCode},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "response with full metadata",
|
||||||
|
clientID: "full-client-id",
|
||||||
|
clientSecret: &ClientSecret{
|
||||||
|
Value: "full-secret",
|
||||||
|
CreatedAt: testTimestamp,
|
||||||
|
},
|
||||||
|
metadata: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/cb1", "https://example.com/cb2"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodClientSecretPost),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode, GrantTypesImplicit},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode, ResponseTypeToken},
|
||||||
|
ClientName: proto.String("Full Test Client"),
|
||||||
|
ClientNameLocalized: map[string]string{
|
||||||
|
"en": "Full Test Client",
|
||||||
|
"es": "Cliente de Prueba Completo",
|
||||||
|
},
|
||||||
|
ClientUri: proto.String("https://example.com"),
|
||||||
|
ClientUriLocalized: map[string]string{
|
||||||
|
"en": "https://example.com/en",
|
||||||
|
},
|
||||||
|
LogoUri: proto.String("https://example.com/logo.png"),
|
||||||
|
Scope: proto.String("openid profile email offline_access"),
|
||||||
|
Contacts: []string{"admin@example.com", "support@example.com"},
|
||||||
|
TosUri: proto.String("https://example.com/tos"),
|
||||||
|
PolicyUri: proto.String("https://example.com/privacy"),
|
||||||
|
JwksUri: proto.String("https://example.com/.well-known/jwks.json"),
|
||||||
|
SoftwareId: proto.String("test-software-v1"),
|
||||||
|
SoftwareVersion: proto.String("1.2.3"),
|
||||||
|
},
|
||||||
|
want: map[string]any{
|
||||||
|
"client_id": "full-client-id",
|
||||||
|
"client_secret": "full-secret",
|
||||||
|
"client_id_issued_at": float64(testTime.Unix()),
|
||||||
|
"client_secret_expires_at": float64(0), // Required per RFC, 0 means no expiration
|
||||||
|
"redirect_uris": []any{"https://example.com/cb1", "https://example.com/cb2"},
|
||||||
|
"token_endpoint_auth_method": TokenEndpointAuthMethodClientSecretPost,
|
||||||
|
"grant_types": []any{GrantTypesAuthorizationCode, GrantTypesImplicit},
|
||||||
|
"response_types": []any{ResponseTypesCode, ResponseTypeToken},
|
||||||
|
"client_name": "Full Test Client",
|
||||||
|
"client_name_localized": map[string]any{
|
||||||
|
"en": "Full Test Client",
|
||||||
|
"es": "Cliente de Prueba Completo",
|
||||||
|
},
|
||||||
|
"client_uri": "https://example.com",
|
||||||
|
"client_uri_localized": map[string]any{
|
||||||
|
"en": "https://example.com/en",
|
||||||
|
},
|
||||||
|
"logo_uri": "https://example.com/logo.png",
|
||||||
|
"scope": "openid profile email offline_access",
|
||||||
|
"contacts": []any{"admin@example.com", "support@example.com"},
|
||||||
|
"tos_uri": "https://example.com/tos",
|
||||||
|
"policy_uri": "https://example.com/privacy",
|
||||||
|
"jwks_uri": "https://example.com/.well-known/jwks.json",
|
||||||
|
"software_id": "test-software-v1",
|
||||||
|
"software_version": "1.2.3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "response with jwks instead of jwks_uri",
|
||||||
|
clientID: "jwks-client",
|
||||||
|
metadata: &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
TokenEndpointAuthMethod: proto.String(TokenEndpointAuthMethodNone),
|
||||||
|
GrantTypes: []string{GrantTypesAuthorizationCode},
|
||||||
|
ResponseTypes: []string{ResponseTypesCode},
|
||||||
|
Jwks: &JsonWebKeySet{
|
||||||
|
Keys: []*JsonWebKey{{
|
||||||
|
Kty: "RSA",
|
||||||
|
KeyTypeParameters: &JsonWebKey_RsaParams{
|
||||||
|
RsaParams: &RsaKeyParameters{
|
||||||
|
N: "example-modulus",
|
||||||
|
E: "AQAB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: map[string]any{
|
||||||
|
"client_id": "jwks-client",
|
||||||
|
"redirect_uris": []any{"https://example.com/callback"},
|
||||||
|
"token_endpoint_auth_method": TokenEndpointAuthMethodNone,
|
||||||
|
"grant_types": []any{GrantTypesAuthorizationCode},
|
||||||
|
"response_types": []any{ResponseTypesCode},
|
||||||
|
"jwks": map[string]any{
|
||||||
|
"keys": []any{
|
||||||
|
map[string]any{
|
||||||
|
"kty": "RSA",
|
||||||
|
"rsa_params": map[string]any{
|
||||||
|
"n": "example-modulus",
|
||||||
|
"e": "AQAB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := WriteRegistrationResponse(&buf, tt.clientID, tt.clientSecret, tt.metadata)
|
||||||
|
|
||||||
|
if tt.wantErr {
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("expected error, got nil")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the JSON output
|
||||||
|
var got map[string]any
|
||||||
|
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||||
|
t.Fatalf("failed to parse JSON output: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the result
|
||||||
|
if diff := cmp.Diff(tt.want, got); diff != "" {
|
||||||
|
t.Errorf("WriteRegistrationResponse() mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the output is valid JSON
|
||||||
|
if !json.Valid(buf.Bytes()) {
|
||||||
|
t.Error("output is not valid JSON")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that client_secret is only present when expected
|
||||||
|
_, hasClientSecret := got["client_secret"]
|
||||||
|
expectedHasSecret := tt.clientSecret != nil
|
||||||
|
if hasClientSecret != expectedHasSecret {
|
||||||
|
t.Errorf("client_secret presence mismatch: got %v, want %v", hasClientSecret, expectedHasSecret)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify timestamp fields presence per RFC 7591
|
||||||
|
_, hasIssuedAt := got["client_id_issued_at"]
|
||||||
|
_, hasExpiresAt := got["client_secret_expires_at"]
|
||||||
|
|
||||||
|
expectedHasIssuedAt := tt.clientSecret != nil && tt.clientSecret.CreatedAt != nil
|
||||||
|
// Per RFC 7591: client_secret_expires_at is REQUIRED if client_secret is issued
|
||||||
|
expectedHasExpiresAt := tt.clientSecret != nil
|
||||||
|
|
||||||
|
if hasIssuedAt != expectedHasIssuedAt {
|
||||||
|
t.Errorf("client_id_issued_at presence mismatch: got %v, want %v", hasIssuedAt, expectedHasIssuedAt)
|
||||||
|
}
|
||||||
|
if hasExpiresAt != expectedHasExpiresAt {
|
||||||
|
t.Errorf("client_secret_expires_at presence mismatch: got %v, want %v", hasExpiresAt, expectedHasExpiresAt)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriteRegistrationResponseEdgeCases(t *testing.T) {
|
||||||
|
t.Run("nil metadata", func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := WriteRegistrationResponse(&buf, "test-client", nil, nil)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error with nil metadata: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty client ID", func(t *testing.T) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
metadata := &Metadata{
|
||||||
|
RedirectUris: []string{"https://example.com/callback"},
|
||||||
|
}
|
||||||
|
err := WriteRegistrationResponse(&buf, "", nil, metadata)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error with empty client ID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var got map[string]any
|
||||||
|
if err := json.Unmarshal(buf.Bytes(), &got); err != nil {
|
||||||
|
t.Fatalf("failed to parse JSON output: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if got["client_id"] != "" {
|
||||||
|
t.Errorf("expected empty client_id, got %v", got["client_id"])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
|
_ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
unsafe "unsafe"
|
unsafe "unsafe"
|
||||||
|
@ -470,7 +471,7 @@ func (x *OkpKeyParameters) GetX() string {
|
||||||
// Represents the client metadata fields defined in RFC 7591 Section 2.
|
// Represents the client metadata fields defined in RFC 7591 Section 2.
|
||||||
// These values are used both as input to registration requests and output in
|
// These values are used both as input to registration requests and output in
|
||||||
// registration responses.
|
// registration responses.
|
||||||
type ClientMetadata struct {
|
type Metadata struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
// Array of redirection URI strings. REQUIRED for clients using flows with
|
// Array of redirection URI strings. REQUIRED for clients using flows with
|
||||||
// redirection.
|
// redirection.
|
||||||
|
@ -525,20 +526,20 @@ type ClientMetadata struct {
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) Reset() {
|
func (x *Metadata) Reset() {
|
||||||
*x = ClientMetadata{}
|
*x = Metadata{}
|
||||||
mi := &file_types_proto_msgTypes[6]
|
mi := &file_types_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) String() string {
|
func (x *Metadata) String() string {
|
||||||
return protoimpl.X.MessageStringOf(x)
|
return protoimpl.X.MessageStringOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ClientMetadata) ProtoMessage() {}
|
func (*Metadata) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ClientMetadata) ProtoReflect() protoreflect.Message {
|
func (x *Metadata) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_types_proto_msgTypes[6]
|
mi := &file_types_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
@ -550,414 +551,554 @@ func (x *ClientMetadata) ProtoReflect() protoreflect.Message {
|
||||||
return mi.MessageOf(x)
|
return mi.MessageOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use ClientMetadata.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Metadata.ProtoReflect.Descriptor instead.
|
||||||
func (*ClientMetadata) Descriptor() ([]byte, []int) {
|
func (*Metadata) Descriptor() ([]byte, []int) {
|
||||||
return file_types_proto_rawDescGZIP(), []int{6}
|
return file_types_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetRedirectUris() []string {
|
func (x *Metadata) GetRedirectUris() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.RedirectUris
|
return x.RedirectUris
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetTokenEndpointAuthMethod() string {
|
func (x *Metadata) GetTokenEndpointAuthMethod() string {
|
||||||
if x != nil && x.TokenEndpointAuthMethod != nil {
|
if x != nil && x.TokenEndpointAuthMethod != nil {
|
||||||
return *x.TokenEndpointAuthMethod
|
return *x.TokenEndpointAuthMethod
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetGrantTypes() []string {
|
func (x *Metadata) GetGrantTypes() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.GrantTypes
|
return x.GrantTypes
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetResponseTypes() []string {
|
func (x *Metadata) GetResponseTypes() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ResponseTypes
|
return x.ResponseTypes
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetClientName() string {
|
func (x *Metadata) GetClientName() string {
|
||||||
if x != nil && x.ClientName != nil {
|
if x != nil && x.ClientName != nil {
|
||||||
return *x.ClientName
|
return *x.ClientName
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetClientNameLocalized() map[string]string {
|
func (x *Metadata) GetClientNameLocalized() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ClientNameLocalized
|
return x.ClientNameLocalized
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetClientUri() string {
|
func (x *Metadata) GetClientUri() string {
|
||||||
if x != nil && x.ClientUri != nil {
|
if x != nil && x.ClientUri != nil {
|
||||||
return *x.ClientUri
|
return *x.ClientUri
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetClientUriLocalized() map[string]string {
|
func (x *Metadata) GetClientUriLocalized() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ClientUriLocalized
|
return x.ClientUriLocalized
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetLogoUri() string {
|
func (x *Metadata) GetLogoUri() string {
|
||||||
if x != nil && x.LogoUri != nil {
|
if x != nil && x.LogoUri != nil {
|
||||||
return *x.LogoUri
|
return *x.LogoUri
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetLogoUriLocalized() map[string]string {
|
func (x *Metadata) GetLogoUriLocalized() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.LogoUriLocalized
|
return x.LogoUriLocalized
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetScope() string {
|
func (x *Metadata) GetScope() string {
|
||||||
if x != nil && x.Scope != nil {
|
if x != nil && x.Scope != nil {
|
||||||
return *x.Scope
|
return *x.Scope
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetContacts() []string {
|
func (x *Metadata) GetContacts() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Contacts
|
return x.Contacts
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetTosUri() string {
|
func (x *Metadata) GetTosUri() string {
|
||||||
if x != nil && x.TosUri != nil {
|
if x != nil && x.TosUri != nil {
|
||||||
return *x.TosUri
|
return *x.TosUri
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetTosUriLocalized() map[string]string {
|
func (x *Metadata) GetTosUriLocalized() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.TosUriLocalized
|
return x.TosUriLocalized
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetPolicyUri() string {
|
func (x *Metadata) GetPolicyUri() string {
|
||||||
if x != nil && x.PolicyUri != nil {
|
if x != nil && x.PolicyUri != nil {
|
||||||
return *x.PolicyUri
|
return *x.PolicyUri
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetPolicyUriLocalized() map[string]string {
|
func (x *Metadata) GetPolicyUriLocalized() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PolicyUriLocalized
|
return x.PolicyUriLocalized
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetJwksUri() string {
|
func (x *Metadata) GetJwksUri() string {
|
||||||
if x != nil && x.JwksUri != nil {
|
if x != nil && x.JwksUri != nil {
|
||||||
return *x.JwksUri
|
return *x.JwksUri
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetJwks() *JsonWebKeySet {
|
func (x *Metadata) GetJwks() *JsonWebKeySet {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Jwks
|
return x.Jwks
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetSoftwareId() string {
|
func (x *Metadata) GetSoftwareId() string {
|
||||||
if x != nil && x.SoftwareId != nil {
|
if x != nil && x.SoftwareId != nil {
|
||||||
return *x.SoftwareId
|
return *x.SoftwareId
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientMetadata) GetSoftwareVersion() string {
|
func (x *Metadata) GetSoftwareVersion() string {
|
||||||
if x != nil && x.SoftwareVersion != nil {
|
if x != nil && x.SoftwareVersion != nil {
|
||||||
return *x.SoftwareVersion
|
return *x.SoftwareVersion
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ClientSecret struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// REQUIRED. The client secret value.
|
||||||
|
Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
|
// OPTIONAL. The expiration time of the client secret.
|
||||||
|
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,proto3,oneof" json:"expires_at,omitempty"`
|
||||||
|
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientSecret) Reset() {
|
||||||
|
*x = ClientSecret{}
|
||||||
|
mi := &file_types_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientSecret) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ClientSecret) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ClientSecret) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_types_proto_msgTypes[7]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ClientSecret.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ClientSecret) Descriptor() ([]byte, []int) {
|
||||||
|
return file_types_proto_rawDescGZIP(), []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientSecret) GetValue() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Value
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientSecret) GetExpiresAt() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.ExpiresAt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientSecret) GetCreatedAt() *timestamppb.Timestamp {
|
||||||
|
if x != nil {
|
||||||
|
return x.CreatedAt
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represents the client registration storage structure.
|
||||||
|
type ClientRegistration struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// Contains the client metadata as requested by the client.
|
||||||
|
RequestMetadata *Metadata `protobuf:"bytes,1,opt,name=request_metadata,json=requestMetadata,proto3" json:"request_metadata,omitempty"`
|
||||||
|
// Contains the client metadata as was returned by the server.
|
||||||
|
ResponseMetadata *Metadata `protobuf:"bytes,2,opt,name=response_metadata,json=responseMetadata,proto3" json:"response_metadata,omitempty"`
|
||||||
|
// OPTIONAL. The "client_secret" parameter is the secret used by the client
|
||||||
|
ClientSecret *ClientSecret `protobuf:"bytes,3,opt,name=client_secret,json=clientSecret,proto3" json:"client_secret,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) Reset() {
|
||||||
|
*x = ClientRegistration{}
|
||||||
|
mi := &file_types_proto_msgTypes[8]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ClientRegistration) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_types_proto_msgTypes[8]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ClientRegistration.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ClientRegistration) Descriptor() ([]byte, []int) {
|
||||||
|
return file_types_proto_rawDescGZIP(), []int{8}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) GetRequestMetadata() *Metadata {
|
||||||
|
if x != nil {
|
||||||
|
return x.RequestMetadata
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) GetResponseMetadata() *Metadata {
|
||||||
|
if x != nil {
|
||||||
|
return x.ResponseMetadata
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientRegistration) GetClientSecret() *ClientSecret {
|
||||||
|
if x != nil {
|
||||||
|
return x.ClientSecret
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var File_types_proto protoreflect.FileDescriptor
|
var File_types_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_types_proto_rawDesc = string([]byte{
|
var file_types_proto_rawDesc = string([]byte{
|
||||||
0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x69,
|
0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x69,
|
||||||
0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x1a, 0x1b,
|
0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x1a, 0x1b,
|
||||||
0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c,
|
0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x61, 0x6c,
|
||||||
0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4d, 0x0a, 0x0d, 0x4a,
|
0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f,
|
||||||
0x73, 0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x3c, 0x0a, 0x04,
|
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d,
|
||||||
0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x65, 0x74,
|
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4d, 0x0a, 0x0d,
|
||||||
0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x73, 0x6f,
|
0x4a, 0x73, 0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x12, 0x3c, 0x0a,
|
||||||
0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, 0x01, 0x92,
|
0x04, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x69, 0x65,
|
||||||
0x01, 0x02, 0x08, 0x01, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0xcf, 0x07, 0x0a, 0x0a, 0x4a,
|
|
||||||
0x73, 0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x03, 0x6b, 0x74, 0x79,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1d, 0xba, 0x48, 0x1a, 0xc8, 0x01, 0x01, 0x72, 0x15,
|
|
||||||
0x10, 0x01, 0x52, 0x03, 0x52, 0x53, 0x41, 0x52, 0x02, 0x45, 0x43, 0x52, 0x03, 0x6f, 0x63, 0x74,
|
|
||||||
0x52, 0x03, 0x4f, 0x4b, 0x50, 0x52, 0x03, 0x6b, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x03, 0x75, 0x73,
|
|
||||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0f, 0xba, 0x48, 0x0c, 0x72, 0x0a, 0x52, 0x03,
|
|
||||||
0x73, 0x69, 0x67, 0x52, 0x03, 0x65, 0x6e, 0x63, 0x48, 0x01, 0x52, 0x03, 0x75, 0x73, 0x65, 0x88,
|
|
||||||
0x01, 0x01, 0x12, 0x25, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20,
|
|
||||||
0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x10,
|
|
||||||
0x01, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4f, 0x70, 0x73, 0x12, 0x1e, 0x0a, 0x03, 0x61, 0x6c, 0x67,
|
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48,
|
|
||||||
0x02, 0x52, 0x03, 0x61, 0x6c, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x03, 0x6b, 0x69, 0x64,
|
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x48,
|
|
||||||
0x03, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x72, 0x73, 0x61,
|
|
||||||
0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
|
|
||||||
0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e,
|
|
||||||
0x52, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
|
|
||||||
0x48, 0x00, 0x52, 0x09, 0x72, 0x73, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3f, 0x0a,
|
|
||||||
0x09, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
|
||||||
0x32, 0x20, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e,
|
|
||||||
0x76, 0x31, 0x2e, 0x45, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
|
|
||||||
0x72, 0x73, 0x48, 0x00, 0x52, 0x08, 0x65, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x54,
|
|
||||||
0x0a, 0x10, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
|
||||||
0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
|
|
||||||
0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6d, 0x6d, 0x65,
|
|
||||||
0x74, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
|
|
||||||
0x73, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x50, 0x61,
|
|
||||||
0x72, 0x61, 0x6d, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x6f, 0x6b, 0x70, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
|
||||||
0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
|
|
||||||
0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x6b, 0x70, 0x4b, 0x65,
|
|
||||||
0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x09, 0x6f,
|
|
||||||
0x6b, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0xab, 0x03, 0xba, 0x48, 0xa7, 0x03, 0x1a,
|
|
||||||
0x66, 0x0a, 0x12, 0x6a, 0x77, 0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
|
||||||
0x73, 0x2e, 0x72, 0x73, 0x61, 0x12, 0x25, 0x72, 0x73, 0x61, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
|
||||||
0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66,
|
|
||||||
0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x52, 0x53, 0x41, 0x27, 0x1a, 0x29, 0x74, 0x68,
|
|
||||||
0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x52, 0x53, 0x41, 0x27, 0x20,
|
|
||||||
0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x72, 0x73, 0x61, 0x5f,
|
|
||||||
0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a, 0x61, 0x0a, 0x11, 0x6a, 0x77, 0x6b, 0x2e, 0x6b,
|
|
||||||
0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x65, 0x63, 0x12, 0x23, 0x65, 0x63,
|
|
||||||
0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75,
|
|
||||||
0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x45, 0x43,
|
|
||||||
0x27, 0x1a, 0x27, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27,
|
|
||||||
0x45, 0x43, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e,
|
|
||||||
0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a, 0x72, 0x0a, 0x12, 0x6a, 0x77,
|
|
||||||
0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6f, 0x63, 0x74,
|
|
||||||
0x12, 0x2b, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
|
||||||
0x6d, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20,
|
|
||||||
0x66, 0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x6f, 0x63, 0x74, 0x27, 0x1a, 0x2f, 0x74,
|
|
||||||
0x68, 0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x6f, 0x63, 0x74, 0x27,
|
|
||||||
0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x79, 0x6d,
|
|
||||||
0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a, 0x66,
|
|
||||||
0x0a, 0x12, 0x6a, 0x77, 0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73,
|
|
||||||
0x2e, 0x6f, 0x6b, 0x70, 0x12, 0x25, 0x6f, 0x6b, 0x70, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73,
|
|
||||||
0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f,
|
|
||||||
0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x4f, 0x4b, 0x50, 0x27, 0x1a, 0x29, 0x74, 0x68, 0x69,
|
|
||||||
0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x4f, 0x4b, 0x50, 0x27, 0x20, 0x7c,
|
|
||||||
0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6f, 0x6b, 0x70, 0x5f, 0x70,
|
|
||||||
0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x42, 0x1c, 0x0a, 0x13, 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x79,
|
|
||||||
0x70, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x05, 0xba,
|
|
||||||
0x48, 0x02, 0x08, 0x00, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x75, 0x73, 0x65, 0x42, 0x06, 0x0a, 0x04,
|
|
||||||
0x5f, 0x61, 0x6c, 0x67, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6b, 0x69, 0x64, 0x22, 0x46, 0x0a, 0x10,
|
|
||||||
0x52, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
|
|
||||||
0x12, 0x18, 0x0a, 0x01, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07,
|
|
||||||
0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01, 0x6e, 0x12, 0x18, 0x0a, 0x01, 0x65, 0x18,
|
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10,
|
|
||||||
0x01, 0x52, 0x01, 0x65, 0x22, 0x76, 0x0a, 0x0f, 0x45, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72,
|
|
||||||
0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x0a, 0x03, 0x63, 0x72, 0x76, 0x18, 0x01,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x42, 0x1d, 0xba, 0x48, 0x1a, 0xc8, 0x01, 0x01, 0x72, 0x15, 0x52, 0x05,
|
|
||||||
0x50, 0x2d, 0x32, 0x35, 0x36, 0x52, 0x05, 0x50, 0x2d, 0x33, 0x38, 0x34, 0x52, 0x05, 0x50, 0x2d,
|
|
||||||
0x35, 0x32, 0x31, 0x52, 0x03, 0x63, 0x72, 0x76, 0x12, 0x18, 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52,
|
|
||||||
0x01, 0x78, 0x12, 0x18, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba,
|
|
||||||
0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01, 0x79, 0x22, 0x32, 0x0a, 0x16,
|
|
||||||
0x53, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61,
|
|
||||||
0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x01, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01, 0x6b,
|
|
||||||
0x22, 0x7e, 0x0a, 0x10, 0x4f, 0x6b, 0x70, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65,
|
|
||||||
0x74, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x03, 0x63, 0x72, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x42, 0x26, 0xba, 0x48, 0x23, 0xc8, 0x01, 0x01, 0x72, 0x1e, 0x52, 0x07, 0x45, 0x64, 0x32,
|
|
||||||
0x35, 0x35, 0x31, 0x39, 0x52, 0x05, 0x45, 0x64, 0x34, 0x34, 0x38, 0x52, 0x06, 0x58, 0x32, 0x35,
|
|
||||||
0x35, 0x31, 0x39, 0x52, 0x04, 0x58, 0x34, 0x34, 0x38, 0x52, 0x03, 0x63, 0x72, 0x76, 0x12, 0x30,
|
|
||||||
0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xba, 0x48, 0x1f, 0xc8, 0x01,
|
|
||||||
0x01, 0x72, 0x1a, 0x10, 0x01, 0x32, 0x16, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30,
|
|
||||||
0x2d, 0x39, 0x2d, 0x5f, 0x5d, 0x2b, 0x3d, 0x7b, 0x30, 0x2c, 0x32, 0x7d, 0x24, 0x52, 0x01, 0x78,
|
|
||||||
0x22, 0x9b, 0x13, 0x0a, 0x0e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
|
||||||
0x61, 0x74, 0x61, 0x12, 0x36, 0x0a, 0x0d, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f,
|
|
||||||
0x75, 0x72, 0x69, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x11, 0xba, 0x48, 0x0e, 0x92,
|
|
||||||
0x01, 0x0b, 0x08, 0x01, 0x22, 0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x0c, 0x72,
|
|
||||||
0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x55, 0x72, 0x69, 0x73, 0x12, 0x76, 0x0a, 0x1a, 0x74,
|
|
||||||
0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x75,
|
|
||||||
0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42,
|
|
||||||
0x34, 0xba, 0x48, 0x31, 0x72, 0x2f, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x52, 0x12, 0x63, 0x6c,
|
|
||||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x74,
|
|
||||||
0x52, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f,
|
|
||||||
0x62, 0x61, 0x73, 0x69, 0x63, 0x48, 0x00, 0x52, 0x17, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e,
|
|
||||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64,
|
|
||||||
0x88, 0x01, 0x01, 0x12, 0xd7, 0x01, 0x0a, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79,
|
|
||||||
0x70, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0xb5, 0x01, 0xba, 0x48, 0xb1, 0x01,
|
|
||||||
0x92, 0x01, 0xad, 0x01, 0x22, 0xaa, 0x01, 0x72, 0xa7, 0x01, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68,
|
|
||||||
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x08,
|
|
||||||
0x69, 0x6d, 0x70, 0x6c, 0x69, 0x63, 0x69, 0x74, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
|
||||||
0x72, 0x64, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65,
|
|
||||||
0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f,
|
|
||||||
0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x2b, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x3a,
|
|
||||||
0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x3a, 0x67, 0x72, 0x61,
|
|
||||||
0x6e, 0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x6a, 0x77, 0x74, 0x2d, 0x62, 0x65, 0x61, 0x72,
|
|
||||||
0x65, 0x72, 0x52, 0x2d, 0x75, 0x72, 0x6e, 0x3a, 0x69, 0x65, 0x74, 0x66, 0x3a, 0x70, 0x61, 0x72,
|
|
||||||
0x61, 0x6d, 0x73, 0x3a, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x3a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x2d,
|
|
||||||
0x74, 0x79, 0x70, 0x65, 0x3a, 0x73, 0x61, 0x6d, 0x6c, 0x32, 0x2d, 0x62, 0x65, 0x61, 0x72, 0x65,
|
|
||||||
0x72, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x3e, 0x0a,
|
|
||||||
0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18,
|
|
||||||
0x04, 0x20, 0x03, 0x28, 0x09, 0x42, 0x17, 0xba, 0x48, 0x14, 0x92, 0x01, 0x11, 0x22, 0x0f, 0x72,
|
|
||||||
0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0d,
|
|
||||||
0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x30, 0x0a,
|
|
||||||
0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01,
|
|
||||||
0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x48, 0x01,
|
|
||||||
0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12,
|
|
||||||
0xa6, 0x01, 0x0a, 0x15, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f,
|
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
|
||||||
0x38, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76,
|
|
||||||
0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
|
||||||
0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
|
|
||||||
0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x38, 0xba, 0x48, 0x35, 0x9a, 0x01,
|
|
||||||
0x32, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d,
|
|
||||||
0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d,
|
|
||||||
0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x07, 0x72, 0x05, 0x10, 0x01,
|
|
||||||
0x18, 0xff, 0x01, 0x52, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x4c,
|
|
||||||
0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65,
|
|
||||||
0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
|
|
||||||
0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48, 0x02, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
|
||||||
0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0xa1, 0x01, 0x0a, 0x14, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
|
||||||
0x74, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18,
|
|
||||||
0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63,
|
|
||||||
0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65,
|
|
||||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x69,
|
|
||||||
0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36,
|
|
||||||
0xba, 0x48, 0x33, 0x9a, 0x01, 0x30, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d,
|
|
||||||
0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a,
|
|
||||||
0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a,
|
|
||||||
0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x72,
|
|
||||||
0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x08, 0x6c, 0x6f,
|
|
||||||
0x67, 0x6f, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
|
|
||||||
0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48, 0x03, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72,
|
|
||||||
0x69, 0x88, 0x01, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x12, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72,
|
|
||||||
0x69, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28,
|
|
||||||
0x0b, 0x32, 0x35, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31,
|
|
||||||
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61,
|
|
||||||
0x74, 0x61, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
|
|
||||||
0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33, 0x9a, 0x01, 0x30,
|
|
||||||
0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b,
|
|
||||||
0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39,
|
|
||||||
0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01,
|
|
||||||
0x52, 0x10, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
|
||||||
0x65, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x42, 0x15, 0xba, 0x48, 0x12, 0x72, 0x10, 0x10, 0x01, 0x32, 0x0c, 0x5e, 0x5c, 0x53, 0x2b,
|
|
||||||
0x28, 0x20, 0x5c, 0x53, 0x2b, 0x29, 0x2a, 0x24, 0x48, 0x04, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70,
|
|
||||||
0x65, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73,
|
|
||||||
0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04,
|
|
||||||
0x72, 0x02, 0x60, 0x01, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73, 0x12, 0x26,
|
|
||||||
0x0a, 0x07, 0x74, 0x6f, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42,
|
|
||||||
0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48, 0x05, 0x52, 0x06, 0x74, 0x6f, 0x73,
|
|
||||||
0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x98, 0x01, 0x0a, 0x11, 0x74, 0x6f, 0x73, 0x5f, 0x75,
|
|
||||||
0x72, 0x69, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x03,
|
|
||||||
0x28, 0x0b, 0x32, 0x34, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39,
|
|
||||||
0x31, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x54, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
|
|
||||||
0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33, 0x9a, 0x01, 0x30,
|
|
||||||
0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b,
|
|
||||||
0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39,
|
|
||||||
0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01,
|
|
||||||
0x52, 0x0f, 0x74, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65,
|
|
||||||
0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18,
|
|
||||||
0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48,
|
|
||||||
0x06, 0x52, 0x09, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12,
|
|
||||||
0xa1, 0x01, 0x0a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x6c,
|
|
||||||
0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37,
|
|
||||||
0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31,
|
|
||||||
0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
|
|
||||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
|
||||||
0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33, 0x9a, 0x01, 0x30, 0x22,
|
|
||||||
0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x31,
|
|
||||||
0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d,
|
|
||||||
0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x52,
|
|
||||||
0x12, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
|
|
||||||
0x7a, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x08, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18,
|
|
||||||
0x11, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48,
|
|
||||||
0x07, 0x52, 0x07, 0x6a, 0x77, 0x6b, 0x73, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x37, 0x0a,
|
|
||||||
0x04, 0x6a, 0x77, 0x6b, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x65,
|
|
||||||
0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x73,
|
0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x73,
|
||||||
0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x48, 0x08, 0x52, 0x04, 0x6a,
|
0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x42, 0x0b, 0xba, 0x48, 0x08, 0xc8, 0x01, 0x01,
|
||||||
0x77, 0x6b, 0x73, 0x88, 0x01, 0x01, 0x12, 0x30, 0x0a, 0x0b, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61,
|
0x92, 0x01, 0x02, 0x08, 0x01, 0x52, 0x04, 0x6b, 0x65, 0x79, 0x73, 0x22, 0xcf, 0x07, 0x0a, 0x0a,
|
||||||
0x72, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07,
|
0x4a, 0x73, 0x6f, 0x6e, 0x57, 0x65, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x03, 0x6b, 0x74,
|
||||||
0x72, 0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x48, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x66, 0x74, 0x77,
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1d, 0xba, 0x48, 0x1a, 0xc8, 0x01, 0x01, 0x72,
|
||||||
0x61, 0x72, 0x65, 0x49, 0x64, 0x88, 0x01, 0x01, 0x12, 0x3a, 0x0a, 0x10, 0x73, 0x6f, 0x66, 0x74,
|
0x15, 0x10, 0x01, 0x52, 0x03, 0x52, 0x53, 0x41, 0x52, 0x02, 0x45, 0x43, 0x52, 0x03, 0x6f, 0x63,
|
||||||
0x77, 0x61, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01,
|
0x74, 0x52, 0x03, 0x4f, 0x4b, 0x50, 0x52, 0x03, 0x6b, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x03, 0x75,
|
||||||
0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x48, 0x0a,
|
0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0f, 0xba, 0x48, 0x0c, 0x72, 0x0a, 0x52,
|
||||||
0x52, 0x0f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f,
|
0x03, 0x73, 0x69, 0x67, 0x52, 0x03, 0x65, 0x6e, 0x63, 0x48, 0x01, 0x52, 0x03, 0x75, 0x73, 0x65,
|
||||||
0x6e, 0x88, 0x01, 0x01, 0x1a, 0x46, 0x0a, 0x18, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61,
|
0x88, 0x01, 0x01, 0x12, 0x25, 0x0a, 0x07, 0x6b, 0x65, 0x79, 0x5f, 0x6f, 0x70, 0x73, 0x18, 0x03,
|
||||||
0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba, 0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
0x10, 0x01, 0x52, 0x06, 0x6b, 0x65, 0x79, 0x4f, 0x70, 0x73, 0x12, 0x1e, 0x0a, 0x03, 0x61, 0x6c,
|
||||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01,
|
||||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17,
|
0x48, 0x02, 0x52, 0x03, 0x61, 0x6c, 0x67, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x03, 0x6b, 0x69,
|
||||||
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01,
|
||||||
|
0x48, 0x03, 0x52, 0x03, 0x6b, 0x69, 0x64, 0x88, 0x01, 0x01, 0x12, 0x42, 0x0a, 0x0a, 0x72, 0x73,
|
||||||
|
0x61, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21,
|
||||||
|
0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31,
|
||||||
|
0x2e, 0x52, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
|
||||||
|
0x73, 0x48, 0x00, 0x52, 0x09, 0x72, 0x73, 0x61, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x3f,
|
||||||
|
0x0a, 0x09, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x20, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31,
|
||||||
|
0x2e, 0x76, 0x31, 0x2e, 0x45, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74,
|
||||||
|
0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x08, 0x65, 0x63, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12,
|
||||||
|
0x54, 0x0a, 0x10, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x69, 0x65, 0x74, 0x66,
|
||||||
|
0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x79, 0x6d, 0x6d,
|
||||||
|
0x65, 0x74, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65,
|
||||||
|
0x72, 0x73, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x50,
|
||||||
|
0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x42, 0x0a, 0x0a, 0x6f, 0x6b, 0x70, 0x5f, 0x70, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x69, 0x65, 0x74, 0x66,
|
||||||
|
0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x6b, 0x70, 0x4b,
|
||||||
|
0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x48, 0x00, 0x52, 0x09,
|
||||||
|
0x6f, 0x6b, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x3a, 0xab, 0x03, 0xba, 0x48, 0xa7, 0x03,
|
||||||
|
0x1a, 0x66, 0x0a, 0x12, 0x6a, 0x77, 0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
||||||
|
0x6d, 0x73, 0x2e, 0x72, 0x73, 0x61, 0x12, 0x25, 0x72, 0x73, 0x61, 0x5f, 0x70, 0x61, 0x72, 0x61,
|
||||||
|
0x6d, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20,
|
||||||
|
0x66, 0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x52, 0x53, 0x41, 0x27, 0x1a, 0x29, 0x74,
|
||||||
|
0x68, 0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x52, 0x53, 0x41, 0x27,
|
||||||
|
0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x72, 0x73, 0x61,
|
||||||
|
0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a, 0x61, 0x0a, 0x11, 0x6a, 0x77, 0x6b, 0x2e,
|
||||||
|
0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x65, 0x63, 0x12, 0x23, 0x65,
|
||||||
|
0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71,
|
||||||
|
0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x45,
|
||||||
|
0x43, 0x27, 0x1a, 0x27, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20,
|
||||||
|
0x27, 0x45, 0x43, 0x27, 0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73,
|
||||||
|
0x2e, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a, 0x72, 0x0a, 0x12, 0x6a,
|
||||||
|
0x77, 0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6f, 0x63,
|
||||||
|
0x74, 0x12, 0x2b, 0x73, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64,
|
||||||
|
0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x6f, 0x63, 0x74, 0x27, 0x1a, 0x2f,
|
||||||
|
0x74, 0x68, 0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x6f, 0x63, 0x74,
|
||||||
|
0x27, 0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x79,
|
||||||
|
0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x1a,
|
||||||
|
0x66, 0x0a, 0x12, 0x6a, 0x77, 0x6b, 0x2e, 0x6b, 0x74, 0x79, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
||||||
|
0x73, 0x2e, 0x6f, 0x6b, 0x70, 0x12, 0x25, 0x6f, 0x6b, 0x70, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d,
|
||||||
|
0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x66,
|
||||||
|
0x6f, 0x72, 0x20, 0x6b, 0x74, 0x79, 0x20, 0x27, 0x4f, 0x4b, 0x50, 0x27, 0x1a, 0x29, 0x74, 0x68,
|
||||||
|
0x69, 0x73, 0x2e, 0x6b, 0x74, 0x79, 0x20, 0x21, 0x3d, 0x20, 0x27, 0x4f, 0x4b, 0x50, 0x27, 0x20,
|
||||||
|
0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6f, 0x6b, 0x70, 0x5f,
|
||||||
|
0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x29, 0x42, 0x1c, 0x0a, 0x13, 0x6b, 0x65, 0x79, 0x5f, 0x74,
|
||||||
|
0x79, 0x70, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x05,
|
||||||
|
0xba, 0x48, 0x02, 0x08, 0x00, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x75, 0x73, 0x65, 0x42, 0x06, 0x0a,
|
||||||
|
0x04, 0x5f, 0x61, 0x6c, 0x67, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6b, 0x69, 0x64, 0x22, 0x46, 0x0a,
|
||||||
|
0x10, 0x52, 0x73, 0x61, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72,
|
||||||
|
0x73, 0x12, 0x18, 0x0a, 0x01, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48,
|
||||||
|
0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01, 0x6e, 0x12, 0x18, 0x0a, 0x01, 0x65,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02,
|
||||||
|
0x10, 0x01, 0x52, 0x01, 0x65, 0x22, 0x76, 0x0a, 0x0f, 0x45, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61,
|
||||||
|
0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x0a, 0x03, 0x63, 0x72, 0x76, 0x18,
|
||||||
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1d, 0xba, 0x48, 0x1a, 0xc8, 0x01, 0x01, 0x72, 0x15, 0x52,
|
||||||
|
0x05, 0x50, 0x2d, 0x32, 0x35, 0x36, 0x52, 0x05, 0x50, 0x2d, 0x33, 0x38, 0x34, 0x52, 0x05, 0x50,
|
||||||
|
0x2d, 0x35, 0x32, 0x31, 0x52, 0x03, 0x63, 0x72, 0x76, 0x12, 0x18, 0x0a, 0x01, 0x78, 0x18, 0x02,
|
||||||
|
0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01,
|
||||||
|
0x52, 0x01, 0x78, 0x12, 0x18, 0x0a, 0x01, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a,
|
||||||
|
0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01, 0x79, 0x22, 0x32, 0x0a,
|
||||||
|
0x16, 0x53, 0x79, 0x6d, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72,
|
||||||
|
0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x01, 0x6b, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01, 0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x01,
|
||||||
|
0x6b, 0x22, 0x7e, 0x0a, 0x10, 0x4f, 0x6b, 0x70, 0x4b, 0x65, 0x79, 0x50, 0x61, 0x72, 0x61, 0x6d,
|
||||||
|
0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x03, 0x63, 0x72, 0x76, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x42, 0x26, 0xba, 0x48, 0x23, 0xc8, 0x01, 0x01, 0x72, 0x1e, 0x52, 0x07, 0x45, 0x64,
|
||||||
|
0x32, 0x35, 0x35, 0x31, 0x39, 0x52, 0x05, 0x45, 0x64, 0x34, 0x34, 0x38, 0x52, 0x06, 0x58, 0x32,
|
||||||
|
0x35, 0x35, 0x31, 0x39, 0x52, 0x04, 0x58, 0x34, 0x34, 0x38, 0x52, 0x03, 0x63, 0x72, 0x76, 0x12,
|
||||||
|
0x30, 0x0a, 0x01, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x22, 0xba, 0x48, 0x1f, 0xc8,
|
||||||
|
0x01, 0x01, 0x72, 0x1a, 0x10, 0x01, 0x32, 0x16, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a,
|
||||||
|
0x30, 0x2d, 0x39, 0x2d, 0x5f, 0x5d, 0x2b, 0x3d, 0x7b, 0x30, 0x2c, 0x32, 0x7d, 0x24, 0x52, 0x01,
|
||||||
|
0x78, 0x22, 0xa5, 0x11, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x36,
|
||||||
|
0x0a, 0x0d, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x73, 0x18,
|
||||||
|
0x01, 0x20, 0x03, 0x28, 0x09, 0x42, 0x11, 0xba, 0x48, 0x0e, 0x92, 0x01, 0x0b, 0x08, 0x01, 0x22,
|
||||||
|
0x07, 0x72, 0x05, 0x10, 0x01, 0x88, 0x01, 0x01, 0x52, 0x0c, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65,
|
||||||
|
0x63, 0x74, 0x55, 0x72, 0x69, 0x73, 0x12, 0x76, 0x0a, 0x1a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f,
|
||||||
|
0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65,
|
||||||
|
0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x34, 0xba, 0x48, 0x31, 0x72,
|
||||||
|
0x2f, 0x52, 0x04, 0x6e, 0x6f, 0x6e, 0x65, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
|
||||||
|
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x70, 0x6f, 0x73, 0x74, 0x52, 0x13, 0x63, 0x6c, 0x69,
|
||||||
|
0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x69, 0x63,
|
||||||
|
0x48, 0x00, 0x52, 0x17, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||||
|
0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x88, 0x01, 0x01, 0x12, 0x1f,
|
||||||
|
0x0a, 0x0b, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x03, 0x20,
|
||||||
|
0x03, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12,
|
||||||
|
0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65,
|
||||||
|
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
|
0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||||
|
0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07,
|
||||||
|
0x72, 0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x48, 0x01, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
|
0x74, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0xa0, 0x01, 0x0a, 0x15, 0x63, 0x6c, 0x69,
|
||||||
|
0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
||||||
|
0x65, 0x64, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
|
||||||
|
0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x6f,
|
||||||
|
0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x38, 0xba, 0x48,
|
||||||
|
0x35, 0x9a, 0x01, 0x32, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41,
|
||||||
|
0x2d, 0x5a, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
|
||||||
|
0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x07, 0x72,
|
||||||
|
0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x52, 0x13, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61,
|
||||||
|
0x6d, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x63,
|
||||||
|
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42,
|
||||||
|
0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48, 0x02, 0x52, 0x09, 0x63, 0x6c, 0x69,
|
||||||
|
0x65, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x9b, 0x01, 0x0a, 0x14, 0x63, 0x6c,
|
||||||
|
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
||||||
|
0x65, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e,
|
||||||
|
0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63,
|
||||||
|
0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33,
|
||||||
|
0x9a, 0x01, 0x30, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d,
|
||||||
|
0x5a, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a,
|
||||||
|
0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03,
|
||||||
|
0x88, 0x01, 0x01, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x55, 0x72, 0x69, 0x4c, 0x6f,
|
||||||
|
0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x28, 0x0a, 0x08, 0x6c, 0x6f, 0x67, 0x6f, 0x5f,
|
||||||
|
0x75, 0x72, 0x69, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03,
|
||||||
|
0x88, 0x01, 0x01, 0x48, 0x03, 0x52, 0x07, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69, 0x88, 0x01,
|
||||||
|
0x01, 0x12, 0x95, 0x01, 0x0a, 0x12, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x6c,
|
||||||
|
0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f,
|
||||||
|
0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31,
|
||||||
|
0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x55, 0x72,
|
||||||
|
0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42,
|
||||||
|
0x36, 0xba, 0x48, 0x33, 0x9a, 0x01, 0x30, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61,
|
||||||
|
0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d,
|
||||||
|
0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24,
|
||||||
|
0x2a, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x52, 0x10, 0x6c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69,
|
||||||
|
0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x73, 0x63, 0x6f,
|
||||||
|
0x70, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x42, 0x15, 0xba, 0x48, 0x12, 0x72, 0x10, 0x10,
|
||||||
|
0x01, 0x32, 0x0c, 0x5e, 0x5c, 0x53, 0x2b, 0x28, 0x20, 0x5c, 0x53, 0x2b, 0x29, 0x2a, 0x24, 0x48,
|
||||||
|
0x04, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x88, 0x01, 0x01, 0x12, 0x28, 0x0a, 0x08, 0x63,
|
||||||
|
0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x42, 0x0c, 0xba,
|
||||||
|
0x48, 0x09, 0x92, 0x01, 0x06, 0x22, 0x04, 0x72, 0x02, 0x60, 0x01, 0x52, 0x08, 0x63, 0x6f, 0x6e,
|
||||||
|
0x74, 0x61, 0x63, 0x74, 0x73, 0x12, 0x26, 0x0a, 0x07, 0x74, 0x6f, 0x73, 0x5f, 0x75, 0x72, 0x69,
|
||||||
|
0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01,
|
||||||
|
0x48, 0x05, 0x52, 0x06, 0x74, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x92, 0x01,
|
||||||
|
0x0a, 0x11, 0x74, 0x6f, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69,
|
||||||
|
0x7a, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x69, 0x65, 0x74, 0x66,
|
||||||
|
0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61,
|
||||||
|
0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
|
||||||
|
0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33, 0x9a, 0x01,
|
||||||
|
0x30, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d,
|
||||||
|
0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d,
|
||||||
|
0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x88, 0x01,
|
||||||
|
0x01, 0x52, 0x0f, 0x74, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
||||||
|
0x65, 0x64, 0x12, 0x2c, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x72, 0x69,
|
||||||
|
0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01,
|
||||||
|
0x48, 0x06, 0x52, 0x09, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01,
|
||||||
|
0x12, 0x9b, 0x01, 0x0a, 0x14, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x5f,
|
||||||
|
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||||
|
0x31, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76,
|
||||||
|
0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63,
|
||||||
|
0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74,
|
||||||
|
0x72, 0x79, 0x42, 0x36, 0xba, 0x48, 0x33, 0x9a, 0x01, 0x30, 0x22, 0x27, 0x72, 0x25, 0x32, 0x23,
|
||||||
|
0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d, 0x28, 0x2d,
|
||||||
|
0x5b, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x30, 0x2d, 0x39, 0x5d, 0x7b, 0x31, 0x2c, 0x38, 0x7d,
|
||||||
|
0x29, 0x2a, 0x24, 0x2a, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x52, 0x12, 0x70, 0x6f, 0x6c, 0x69,
|
||||||
|
0x63, 0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x28,
|
||||||
|
0x0a, 0x08, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0x88, 0x01, 0x01, 0x48, 0x07, 0x52, 0x07, 0x6a, 0x77,
|
||||||
|
0x6b, 0x73, 0x55, 0x72, 0x69, 0x88, 0x01, 0x01, 0x12, 0x37, 0x0a, 0x04, 0x6a, 0x77, 0x6b, 0x73,
|
||||||
|
0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66,
|
||||||
|
0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x73, 0x6f, 0x6e, 0x57, 0x65, 0x62,
|
||||||
|
0x4b, 0x65, 0x79, 0x53, 0x65, 0x74, 0x48, 0x08, 0x52, 0x04, 0x6a, 0x77, 0x6b, 0x73, 0x88, 0x01,
|
||||||
|
0x01, 0x12, 0x30, 0x0a, 0x0b, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x69, 0x64,
|
||||||
|
0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x18,
|
||||||
|
0xff, 0x01, 0x48, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x49, 0x64,
|
||||||
|
0x88, 0x01, 0x01, 0x12, 0x3a, 0x0a, 0x10, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5f,
|
||||||
|
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba,
|
||||||
|
0x48, 0x07, 0x72, 0x05, 0x10, 0x01, 0x18, 0xff, 0x01, 0x48, 0x0a, 0x52, 0x0f, 0x73, 0x6f, 0x66,
|
||||||
|
0x74, 0x77, 0x61, 0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x1a,
|
||||||
|
0x46, 0x0a, 0x18, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x6f, 0x63,
|
||||||
|
0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||||
|
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||||
|
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||||
|
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17, 0x43, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
|
0x74, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74,
|
||||||
|
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
|
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x43,
|
||||||
|
0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
||||||
0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
||||||
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
|
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
|
||||||
0x02, 0x38, 0x01, 0x1a, 0x43, 0x0a, 0x15, 0x4c, 0x6f, 0x67, 0x6f, 0x55, 0x72, 0x69, 0x4c, 0x6f,
|
0x02, 0x38, 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x54, 0x6f, 0x73, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63,
|
||||||
0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
|
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
|
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x42, 0x0a, 0x14, 0x54, 0x6f, 0x73, 0x55,
|
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17, 0x50, 0x6f, 0x6c, 0x69, 0x63,
|
||||||
0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x6e, 0x74,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x45, 0x0a, 0x17,
|
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x3a, 0x7e,
|
||||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x55, 0x72, 0x69, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a,
|
0xba, 0x48, 0x7b, 0x1a, 0x79, 0x0a, 0x25, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65,
|
||||||
0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01,
|
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x6d, 0x75, 0x74, 0x75,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
0x61, 0x6c, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x6a, 0x77,
|
||||||
0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a,
|
0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6a, 0x77, 0x6b, 0x73, 0x20,
|
||||||
0x02, 0x38, 0x01, 0x3a, 0x7e, 0xba, 0x48, 0x7b, 0x1a, 0x79, 0x0a, 0x25, 0x63, 0x6c, 0x69, 0x65,
|
0x61, 0x72, 0x65, 0x20, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x65, 0x78, 0x63,
|
||||||
0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x6a, 0x77, 0x6b, 0x73,
|
0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x1a, 0x26, 0x21, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69,
|
||||||
0x5f, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x6f,
|
0x73, 0x2e, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x21,
|
||||||
0x6e, 0x12, 0x28, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x20, 0x61, 0x6e, 0x64, 0x20,
|
0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6a, 0x77, 0x6b, 0x73, 0x29, 0x42, 0x1d,
|
||||||
0x6a, 0x77, 0x6b, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6d, 0x75, 0x74, 0x75, 0x61, 0x6c, 0x6c,
|
0x0a, 0x1b, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
||||||
0x79, 0x20, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x1a, 0x26, 0x21, 0x68, 0x61,
|
0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x0e, 0x0a,
|
||||||
0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x29,
|
0x0c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0d, 0x0a,
|
||||||
0x20, 0x7c, 0x7c, 0x20, 0x21, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6a, 0x77,
|
0x0b, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x0b, 0x0a, 0x09,
|
||||||
0x6b, 0x73, 0x29, 0x42, 0x1d, 0x0a, 0x1b, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x65, 0x6e,
|
0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x73, 0x63,
|
||||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68,
|
0x6f, 0x70, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x74, 0x6f, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x42,
|
||||||
0x6f, 0x64, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61,
|
0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x0b,
|
||||||
0x6d, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x75, 0x72,
|
0x0a, 0x09, 0x5f, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x07, 0x0a, 0x05, 0x5f,
|
||||||
0x69, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x6f, 0x67, 0x6f, 0x5f, 0x75, 0x72, 0x69, 0x42, 0x08,
|
0x6a, 0x77, 0x6b, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
|
||||||
0x0a, 0x06, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x74, 0x6f, 0x73,
|
0x65, 0x5f, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x73, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72,
|
||||||
0x5f, 0x75, 0x72, 0x69, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f,
|
0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xc2, 0x01, 0x0a, 0x0c, 0x43, 0x6c,
|
||||||
0x75, 0x72, 0x69, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6a, 0x77, 0x6b, 0x73, 0x5f, 0x75, 0x72, 0x69,
|
0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x05, 0x76, 0x61,
|
||||||
0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6a, 0x77, 0x6b, 0x73, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x73, 0x6f,
|
0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0a, 0xba, 0x48, 0x07, 0xc8, 0x01,
|
||||||
0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x69, 0x64, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x73, 0x6f,
|
0x01, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0a,
|
||||||
0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0xba,
|
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37,
|
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f,
|
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x00, 0x52, 0x09,
|
||||||
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x88, 0x01, 0x01, 0x12, 0x41, 0x0a, 0x0a,
|
||||||
0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69,
|
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x75, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x72, 0x66, 0x63, 0x37,
|
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||||
0x35, 0x39, 0x31, 0x76, 0x31, 0x3b, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x76, 0x31, 0xa2,
|
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x42, 0x06, 0xba, 0x48,
|
||||||
0x02, 0x03, 0x49, 0x52, 0x58, 0xaa, 0x02, 0x0f, 0x49, 0x65, 0x74, 0x66, 0x2e, 0x52, 0x66, 0x63,
|
0x03, 0xc8, 0x01, 0x01, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x42,
|
||||||
0x37, 0x35, 0x39, 0x31, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0f, 0x49, 0x65, 0x74, 0x66, 0x5c, 0x52,
|
0x0d, 0x0a, 0x0b, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x22, 0xf6,
|
||||||
0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1b, 0x49, 0x65, 0x74, 0x66,
|
0x01, 0x0a, 0x12, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72,
|
||||||
0x5c, 0x52, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||||
0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x11, 0x49, 0x65, 0x74, 0x66, 0x3a, 0x3a,
|
0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x52, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
0x19, 0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76,
|
||||||
0x74, 0x6f, 0x33,
|
0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8,
|
||||||
|
0x01, 0x01, 0x52, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x12, 0x4e, 0x0a, 0x11, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f,
|
||||||
|
0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
|
||||||
|
0x2e, 0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31,
|
||||||
|
0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01,
|
||||||
|
0x01, 0x52, 0x10, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64,
|
||||||
|
0x61, 0x74, 0x61, 0x12, 0x42, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65,
|
||||||
|
0x63, 0x72, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x69, 0x65, 0x74,
|
||||||
|
0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x69,
|
||||||
|
0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
|
0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x42, 0xba, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e,
|
||||||
|
0x69, 0x65, 0x74, 0x66, 0x2e, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x76, 0x31, 0x42,
|
||||||
|
0x0a, 0x54, 0x79, 0x70, 0x65, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x39, 0x67,
|
||||||
|
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69,
|
||||||
|
0x75, 0x6d, 0x2f, 0x70, 0x6f, 0x6d, 0x65, 0x72, 0x69, 0x75, 0x6d, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||||
|
0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x72, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x76, 0x31, 0x3b, 0x72,
|
||||||
|
0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x49, 0x52, 0x58, 0xaa, 0x02,
|
||||||
|
0x0f, 0x49, 0x65, 0x74, 0x66, 0x2e, 0x52, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x2e, 0x56, 0x31,
|
||||||
|
0xca, 0x02, 0x0f, 0x49, 0x65, 0x74, 0x66, 0x5c, 0x52, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31, 0x5c,
|
||||||
|
0x56, 0x31, 0xe2, 0x02, 0x1b, 0x49, 0x65, 0x74, 0x66, 0x5c, 0x52, 0x66, 0x63, 0x37, 0x35, 0x39,
|
||||||
|
0x31, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
|
0xea, 0x02, 0x11, 0x49, 0x65, 0x74, 0x66, 0x3a, 0x3a, 0x52, 0x66, 0x63, 0x37, 0x35, 0x39, 0x31,
|
||||||
|
0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
})
|
})
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -972,7 +1113,7 @@ func file_types_proto_rawDescGZIP() []byte {
|
||||||
return file_types_proto_rawDescData
|
return file_types_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
|
var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
|
||||||
var file_types_proto_goTypes = []any{
|
var file_types_proto_goTypes = []any{
|
||||||
(*JsonWebKeySet)(nil), // 0: ietf.rfc7591.v1.JsonWebKeySet
|
(*JsonWebKeySet)(nil), // 0: ietf.rfc7591.v1.JsonWebKeySet
|
||||||
(*JsonWebKey)(nil), // 1: ietf.rfc7591.v1.JsonWebKey
|
(*JsonWebKey)(nil), // 1: ietf.rfc7591.v1.JsonWebKey
|
||||||
|
@ -980,12 +1121,15 @@ var file_types_proto_goTypes = []any{
|
||||||
(*EcKeyParameters)(nil), // 3: ietf.rfc7591.v1.EcKeyParameters
|
(*EcKeyParameters)(nil), // 3: ietf.rfc7591.v1.EcKeyParameters
|
||||||
(*SymmetricKeyParameters)(nil), // 4: ietf.rfc7591.v1.SymmetricKeyParameters
|
(*SymmetricKeyParameters)(nil), // 4: ietf.rfc7591.v1.SymmetricKeyParameters
|
||||||
(*OkpKeyParameters)(nil), // 5: ietf.rfc7591.v1.OkpKeyParameters
|
(*OkpKeyParameters)(nil), // 5: ietf.rfc7591.v1.OkpKeyParameters
|
||||||
(*ClientMetadata)(nil), // 6: ietf.rfc7591.v1.ClientMetadata
|
(*Metadata)(nil), // 6: ietf.rfc7591.v1.Metadata
|
||||||
nil, // 7: ietf.rfc7591.v1.ClientMetadata.ClientNameLocalizedEntry
|
(*ClientSecret)(nil), // 7: ietf.rfc7591.v1.ClientSecret
|
||||||
nil, // 8: ietf.rfc7591.v1.ClientMetadata.ClientUriLocalizedEntry
|
(*ClientRegistration)(nil), // 8: ietf.rfc7591.v1.ClientRegistration
|
||||||
nil, // 9: ietf.rfc7591.v1.ClientMetadata.LogoUriLocalizedEntry
|
nil, // 9: ietf.rfc7591.v1.Metadata.ClientNameLocalizedEntry
|
||||||
nil, // 10: ietf.rfc7591.v1.ClientMetadata.TosUriLocalizedEntry
|
nil, // 10: ietf.rfc7591.v1.Metadata.ClientUriLocalizedEntry
|
||||||
nil, // 11: ietf.rfc7591.v1.ClientMetadata.PolicyUriLocalizedEntry
|
nil, // 11: ietf.rfc7591.v1.Metadata.LogoUriLocalizedEntry
|
||||||
|
nil, // 12: ietf.rfc7591.v1.Metadata.TosUriLocalizedEntry
|
||||||
|
nil, // 13: ietf.rfc7591.v1.Metadata.PolicyUriLocalizedEntry
|
||||||
|
(*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp
|
||||||
}
|
}
|
||||||
var file_types_proto_depIdxs = []int32{
|
var file_types_proto_depIdxs = []int32{
|
||||||
1, // 0: ietf.rfc7591.v1.JsonWebKeySet.keys:type_name -> ietf.rfc7591.v1.JsonWebKey
|
1, // 0: ietf.rfc7591.v1.JsonWebKeySet.keys:type_name -> ietf.rfc7591.v1.JsonWebKey
|
||||||
|
@ -993,17 +1137,22 @@ var file_types_proto_depIdxs = []int32{
|
||||||
3, // 2: ietf.rfc7591.v1.JsonWebKey.ec_params:type_name -> ietf.rfc7591.v1.EcKeyParameters
|
3, // 2: ietf.rfc7591.v1.JsonWebKey.ec_params:type_name -> ietf.rfc7591.v1.EcKeyParameters
|
||||||
4, // 3: ietf.rfc7591.v1.JsonWebKey.symmetric_params:type_name -> ietf.rfc7591.v1.SymmetricKeyParameters
|
4, // 3: ietf.rfc7591.v1.JsonWebKey.symmetric_params:type_name -> ietf.rfc7591.v1.SymmetricKeyParameters
|
||||||
5, // 4: ietf.rfc7591.v1.JsonWebKey.okp_params:type_name -> ietf.rfc7591.v1.OkpKeyParameters
|
5, // 4: ietf.rfc7591.v1.JsonWebKey.okp_params:type_name -> ietf.rfc7591.v1.OkpKeyParameters
|
||||||
7, // 5: ietf.rfc7591.v1.ClientMetadata.client_name_localized:type_name -> ietf.rfc7591.v1.ClientMetadata.ClientNameLocalizedEntry
|
9, // 5: ietf.rfc7591.v1.Metadata.client_name_localized:type_name -> ietf.rfc7591.v1.Metadata.ClientNameLocalizedEntry
|
||||||
8, // 6: ietf.rfc7591.v1.ClientMetadata.client_uri_localized:type_name -> ietf.rfc7591.v1.ClientMetadata.ClientUriLocalizedEntry
|
10, // 6: ietf.rfc7591.v1.Metadata.client_uri_localized:type_name -> ietf.rfc7591.v1.Metadata.ClientUriLocalizedEntry
|
||||||
9, // 7: ietf.rfc7591.v1.ClientMetadata.logo_uri_localized:type_name -> ietf.rfc7591.v1.ClientMetadata.LogoUriLocalizedEntry
|
11, // 7: ietf.rfc7591.v1.Metadata.logo_uri_localized:type_name -> ietf.rfc7591.v1.Metadata.LogoUriLocalizedEntry
|
||||||
10, // 8: ietf.rfc7591.v1.ClientMetadata.tos_uri_localized:type_name -> ietf.rfc7591.v1.ClientMetadata.TosUriLocalizedEntry
|
12, // 8: ietf.rfc7591.v1.Metadata.tos_uri_localized:type_name -> ietf.rfc7591.v1.Metadata.TosUriLocalizedEntry
|
||||||
11, // 9: ietf.rfc7591.v1.ClientMetadata.policy_uri_localized:type_name -> ietf.rfc7591.v1.ClientMetadata.PolicyUriLocalizedEntry
|
13, // 9: ietf.rfc7591.v1.Metadata.policy_uri_localized:type_name -> ietf.rfc7591.v1.Metadata.PolicyUriLocalizedEntry
|
||||||
0, // 10: ietf.rfc7591.v1.ClientMetadata.jwks:type_name -> ietf.rfc7591.v1.JsonWebKeySet
|
0, // 10: ietf.rfc7591.v1.Metadata.jwks:type_name -> ietf.rfc7591.v1.JsonWebKeySet
|
||||||
11, // [11:11] is the sub-list for method output_type
|
14, // 11: ietf.rfc7591.v1.ClientSecret.expires_at:type_name -> google.protobuf.Timestamp
|
||||||
11, // [11:11] is the sub-list for method input_type
|
14, // 12: ietf.rfc7591.v1.ClientSecret.created_at:type_name -> google.protobuf.Timestamp
|
||||||
11, // [11:11] is the sub-list for extension type_name
|
6, // 13: ietf.rfc7591.v1.ClientRegistration.request_metadata:type_name -> ietf.rfc7591.v1.Metadata
|
||||||
11, // [11:11] is the sub-list for extension extendee
|
6, // 14: ietf.rfc7591.v1.ClientRegistration.response_metadata:type_name -> ietf.rfc7591.v1.Metadata
|
||||||
0, // [0:11] is the sub-list for field type_name
|
7, // 15: ietf.rfc7591.v1.ClientRegistration.client_secret:type_name -> ietf.rfc7591.v1.ClientSecret
|
||||||
|
16, // [16:16] is the sub-list for method output_type
|
||||||
|
16, // [16:16] is the sub-list for method input_type
|
||||||
|
16, // [16:16] is the sub-list for extension type_name
|
||||||
|
16, // [16:16] is the sub-list for extension extendee
|
||||||
|
0, // [0:16] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_types_proto_init() }
|
func init() { file_types_proto_init() }
|
||||||
|
@ -1018,13 +1167,14 @@ func file_types_proto_init() {
|
||||||
(*JsonWebKey_OkpParams)(nil),
|
(*JsonWebKey_OkpParams)(nil),
|
||||||
}
|
}
|
||||||
file_types_proto_msgTypes[6].OneofWrappers = []any{}
|
file_types_proto_msgTypes[6].OneofWrappers = []any{}
|
||||||
|
file_types_proto_msgTypes[7].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 12,
|
NumMessages: 14,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ syntax = "proto3";
|
||||||
package ietf.rfc7591.v1;
|
package ietf.rfc7591.v1;
|
||||||
|
|
||||||
import "buf/validate/validate.proto";
|
import "buf/validate/validate.proto";
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
option go_package = "github.com/pomerium/pomerium/internal/rfc7591";
|
option go_package = "github.com/pomerium/pomerium/internal/rfc7591";
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ message OkpKeyParameters {
|
||||||
// Represents the client metadata fields defined in RFC 7591 Section 2.
|
// Represents the client metadata fields defined in RFC 7591 Section 2.
|
||||||
// These values are used both as input to registration requests and output in
|
// These values are used both as input to registration requests and output in
|
||||||
// registration responses.
|
// registration responses.
|
||||||
message ClientMetadata {
|
message Metadata {
|
||||||
// Array of redirection URI strings. REQUIRED for clients using flows with
|
// Array of redirection URI strings. REQUIRED for clients using flows with
|
||||||
// redirection.
|
// redirection.
|
||||||
repeated string redirect_uris = 1 [(buf.validate.field).repeated = {
|
repeated string redirect_uris = 1 [(buf.validate.field).repeated = {
|
||||||
|
@ -169,23 +170,11 @@ message ClientMetadata {
|
||||||
|
|
||||||
// OPTIONAL. Array of OAuth 2.0 grant type strings that the client can use.
|
// OPTIONAL. Array of OAuth 2.0 grant type strings that the client can use.
|
||||||
// If omitted, defaults to ["authorization_code"].
|
// If omitted, defaults to ["authorization_code"].
|
||||||
repeated string grant_types = 3 [(buf.validate.field).repeated.items.string = {
|
repeated string grant_types = 3;
|
||||||
in: [
|
|
||||||
"authorization_code",
|
|
||||||
"implicit",
|
|
||||||
"password",
|
|
||||||
"client_credentials",
|
|
||||||
"refresh_token",
|
|
||||||
"urn:ietf:params:oauth:grant-type:jwt-bearer",
|
|
||||||
"urn:ietf:params:oauth:grant-type:saml2-bearer"
|
|
||||||
],
|
|
||||||
}];
|
|
||||||
|
|
||||||
// OPTIONAL. Array of the OAuth 2.0 response type strings that the client can
|
// OPTIONAL. Array of the OAuth 2.0 response type strings that the client can
|
||||||
// use. If omitted, defaults to ["code"].
|
// use. If omitted, defaults to ["code"].
|
||||||
repeated string response_types = 4 [(buf.validate.field).repeated.items.string = {
|
repeated string response_types = 4;
|
||||||
in: ["code", "token"],
|
|
||||||
}];
|
|
||||||
|
|
||||||
// OPTIONAL. Human-readable string name of the client. RECOMMENDED.
|
// OPTIONAL. Human-readable string name of the client. RECOMMENDED.
|
||||||
optional string client_name = 5 [(buf.validate.field).string = {min_len: 1, max_len: 255}];
|
optional string client_name = 5 [(buf.validate.field).string = {min_len: 1, max_len: 255}];
|
||||||
|
@ -266,3 +255,32 @@ message ClientMetadata {
|
||||||
message: "jwks_uri and jwks are mutually exclusive",
|
message: "jwks_uri and jwks are mutually exclusive",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ClientSecret {
|
||||||
|
// REQUIRED. The client secret value.
|
||||||
|
string value = 1 [
|
||||||
|
(buf.validate.field).required = true,
|
||||||
|
(buf.validate.field).string.min_len = 1
|
||||||
|
];
|
||||||
|
// OPTIONAL. The expiration time of the client secret.
|
||||||
|
optional google.protobuf.Timestamp expires_at = 2;
|
||||||
|
google.protobuf.Timestamp created_at = 3 [
|
||||||
|
(buf.validate.field).required = true
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Represents the client registration storage structure.
|
||||||
|
message ClientRegistration {
|
||||||
|
// Contains the client metadata as requested by the client.
|
||||||
|
Metadata request_metadata = 1 [
|
||||||
|
(buf.validate.field).required = true
|
||||||
|
];
|
||||||
|
|
||||||
|
// Contains the client metadata as was returned by the server.
|
||||||
|
Metadata response_metadata = 2 [
|
||||||
|
(buf.validate.field).required = true
|
||||||
|
];
|
||||||
|
|
||||||
|
// OPTIONAL. The "client_secret" parameter is the secret used by the client
|
||||||
|
ClientSecret client_secret = 3;
|
||||||
|
}
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
package rfc7591v1_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/bufbuild/protovalidate-go"
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"google.golang.org/protobuf/encoding/protojson"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
"google.golang.org/protobuf/testing/protocmp"
|
|
||||||
|
|
||||||
rfc7591 "github.com/pomerium/pomerium/internal/rfc7591"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestValidation(t *testing.T) {
|
|
||||||
v := &rfc7591.JsonWebKey{Kty: "Invalid"}
|
|
||||||
require.ErrorContains(t, protovalidate.Validate(v), `kty: value must be in list [RSA, EC, oct, OKP] [string.in]`)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJSONMarshal(t *testing.T) {
|
|
||||||
data := `
|
|
||||||
{
|
|
||||||
"redirect_uris": [
|
|
||||||
"http://localhost:8002/oauth/callback"
|
|
||||||
],
|
|
||||||
"token_endpoint_auth_method": "none",
|
|
||||||
"grant_types": [
|
|
||||||
"authorization_code",
|
|
||||||
"refresh_token"
|
|
||||||
],
|
|
||||||
"response_types": [
|
|
||||||
"code"
|
|
||||||
],
|
|
||||||
"client_name": "MCP Inspector",
|
|
||||||
"client_uri": "https://github.com/modelcontextprotocol/inspector"
|
|
||||||
}`
|
|
||||||
v := &rfc7591.ClientMetadata{}
|
|
||||||
require.NoError(t, protojson.Unmarshal([]byte(data), v))
|
|
||||||
diff := cmp.Diff(&rfc7591.ClientMetadata{
|
|
||||||
RedirectUris: []string{"http://localhost:8002/oauth/callback"},
|
|
||||||
TokenEndpointAuthMethod: proto.String("none"),
|
|
||||||
GrantTypes: []string{"authorization_code", "refresh_token"},
|
|
||||||
ResponseTypes: []string{"code"},
|
|
||||||
ClientName: proto.String("MCP Inspector"),
|
|
||||||
ClientUri: proto.String("https://github.com/modelcontextprotocol/inspector"),
|
|
||||||
}, v, protocmp.Transform())
|
|
||||||
require.Empty(t, diff)
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue