Skip to content

Commit 03d8e2c

Browse files
authored
feat(api-token): Add org_name to token payload (#1095)
Signed-off-by: Javier Rodriguez <[email protected]>
1 parent 31a3a73 commit 03d8e2c

File tree

10 files changed

+102
-60
lines changed

10 files changed

+102
-60
lines changed

app/controlplane/api/controlplane/v1/api_token.pb.go

Lines changed: 55 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/api_token.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ message APITokenItem {
7171
string name = 7;
7272
string description = 2;
7373
string organization_id = 3;
74+
string organization_name = 8;
7475
google.protobuf.Timestamp created_at = 4;
7576
google.protobuf.Timestamp revoked_at = 5;
7677
google.protobuf.Timestamp expires_at = 6;

app/controlplane/api/gen/frontend/controlplane/v1/api_token.ts

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/cmd/wire_gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/internal/service/apitoken.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,12 @@ func (s *APITokenService) Revoke(ctx context.Context, req *pb.APITokenServiceRev
102102

103103
func apiTokenBizToPb(in *biz.APIToken) *pb.APITokenItem {
104104
res := &pb.APITokenItem{
105-
Id: in.ID.String(),
106-
Name: in.Name,
107-
Description: in.Description, OrganizationId: in.OrganizationID.String(),
108-
CreatedAt: timestamppb.New(*in.CreatedAt),
105+
Id: in.ID.String(),
106+
Name: in.Name,
107+
OrganizationId: in.OrganizationID.String(),
108+
OrganizationName: in.OrganizationName,
109+
Description: in.Description,
110+
CreatedAt: timestamppb.New(*in.CreatedAt),
109111
}
110112

111113
if in.ExpiresAt != nil {

app/controlplane/internal/usercontext/apitoken_middleware_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ func TestWithCurrentAPITokenAndOrgMiddleware(t *testing.T) {
9999
t.Run(tc.name, func(t *testing.T) {
100100
apiTokenRepo := bizMocks.NewAPITokenRepo(t)
101101
orgRepo := bizMocks.NewOrganizationRepo(t)
102-
apiTokenUC, err := biz.NewAPITokenUseCase(apiTokenRepo, &conf.Auth{GeneratedJwsHmacSecret: "test"}, nil, nil)
102+
apiTokenUC, err := biz.NewAPITokenUseCase(apiTokenRepo, &conf.Auth{GeneratedJwsHmacSecret: "test"}, nil, nil, nil)
103103
require.NoError(t, err)
104104
orgUC := biz.NewOrganizationUseCase(orgRepo, nil, nil, nil, nil, nil)
105105
require.NoError(t, err)

app/controlplane/pkg/biz/apitoken.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ type APIToken struct {
3838
// This is the JWT value returned only during creation
3939
JWT string
4040
// Tokens are scoped to organizations
41-
OrganizationID uuid.UUID
42-
CreatedAt *time.Time
41+
OrganizationID uuid.UUID
42+
OrganizationName string
43+
CreatedAt *time.Time
4344
// When the token expires
4445
ExpiresAt *time.Time
4546
// When the token was manually revoked
@@ -61,15 +62,18 @@ type APITokenUseCase struct {
6162
jwtBuilder *apitoken.Builder
6263
enforcer *authz.Enforcer
6364
DefaultAuthzPolicies []*authz.Policy
65+
// Use Cases
66+
orgUseCase *OrganizationUseCase
6467
}
6568

6669
type APITokenSyncerUseCase struct {
6770
base *APITokenUseCase
6871
}
6972

70-
func NewAPITokenUseCase(apiTokenRepo APITokenRepo, conf *conf.Auth, authzE *authz.Enforcer, logger log.Logger) (*APITokenUseCase, error) {
73+
func NewAPITokenUseCase(apiTokenRepo APITokenRepo, conf *conf.Auth, authzE *authz.Enforcer, orgUseCase *OrganizationUseCase, logger log.Logger) (*APITokenUseCase, error) {
7174
uc := &APITokenUseCase{
7275
apiTokenRepo: apiTokenRepo,
76+
orgUseCase: orgUseCase,
7377
logger: servicelogger.ScopedHelper(logger, "biz/APITokenUseCase"),
7478
enforcer: authzE,
7579
DefaultAuthzPolicies: []*authz.Policy{
@@ -125,6 +129,12 @@ func (uc *APITokenUseCase) Create(ctx context.Context, name string, description
125129
*expiresAt = time.Now().Add(*expiresIn)
126130
}
127131

132+
// Retrieve the organization
133+
org, err := uc.orgUseCase.FindByID(ctx, orgID)
134+
if err != nil {
135+
return nil, fmt.Errorf("finding organization: %w", err)
136+
}
137+
128138
// NOTE: the expiration time is stored just for reference, it's also encoded in the JWT
129139
// We store it since Chainloop will not have access to the JWT to check the expiration once created
130140
token, err := uc.apiTokenRepo.Create(ctx, name, description, expiresAt, orgUUID)
@@ -136,7 +146,7 @@ func (uc *APITokenUseCase) Create(ctx context.Context, name string, description
136146
}
137147

138148
// generate the JWT
139-
token.JWT, err = uc.jwtBuilder.GenerateJWT(token.OrganizationID.String(), token.ID.String(), expiresAt)
149+
token.JWT, err = uc.jwtBuilder.GenerateJWT(token.OrganizationID.String(), org.Name, token.ID.String(), expiresAt)
140150
if err != nil {
141151
return nil, fmt.Errorf("generating jwt: %w", err)
142152
}

app/controlplane/pkg/biz/testhelpers/wire_gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/pkg/jwt/apitoken/apitoken.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ func NewBuilder(opts ...NewOpt) (*Builder, error) {
6666
return b, nil
6767
}
6868

69-
// it can both expire and being revoked, revocation is performed by checking the keyID against our revocation list
70-
func (ra *Builder) GenerateJWT(orgID, keyID string, expiresAt *time.Time) (string, error) {
69+
// GenerateJWT creates a new JWT token for the given organization and keyID
70+
func (ra *Builder) GenerateJWT(orgID, orgName, keyID string, expiresAt *time.Time) (string, error) {
7171
claims := CustomClaims{
7272
orgID,
73+
orgName,
7374
jwt.RegisteredClaims{
74-
// Key identifier so we can check it's revocation status
75+
// Key identifier so we can check its revocation status
7576
ID: keyID,
7677
Issuer: ra.issuer,
7778
Audience: jwt.ClaimStrings{Audience},
@@ -88,6 +89,7 @@ func (ra *Builder) GenerateJWT(orgID, keyID string, expiresAt *time.Time) (strin
8889
}
8990

9091
type CustomClaims struct {
91-
OrgID string `json:"org_id"`
92+
OrgID string `json:"org_id"`
93+
OrgName string `json:"org_name"`
9294
jwt.RegisteredClaims
9395
}

app/controlplane/pkg/jwt/apitoken/apitoken_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestGenerateJWT(t *testing.T) {
7373
b, err := NewBuilder(WithIssuer("my-issuer"), WithKeySecret(hmacSecret))
7474
require.NoError(t, err)
7575

76-
token, err := b.GenerateJWT("org-id", "key-id", toPtrTime(time.Now().Add(1*time.Hour)))
76+
token, err := b.GenerateJWT("org-id", "org-name", "key-id", toPtrTime(time.Now().Add(1*time.Hour)))
7777
assert.NoError(t, err)
7878
assert.NotEmpty(t, token)
7979

@@ -86,6 +86,7 @@ func TestGenerateJWT(t *testing.T) {
8686
require.NoError(t, err)
8787
assert.True(t, tokenInfo.Valid)
8888
assert.Equal(t, "org-id", claims.OrgID)
89+
assert.Equal(t, "org-name", claims.OrgName)
8990
assert.Equal(t, "key-id", claims.ID)
9091
assert.Equal(t, "my-issuer", claims.Issuer)
9192
assert.Contains(t, claims.Audience, Audience)

0 commit comments

Comments
 (0)