Skip to content

Commit

Permalink
Merge pull request #802 from rithujohn191/token-revocation
Browse files Browse the repository at this point in the history
api: adding a gRPC call for revoking refresh tokens.
  • Loading branch information
rithujohn191 committed Feb 15, 2017
2 parents b119ffd + 1ec19d4 commit 7e9dc83
Show file tree
Hide file tree
Showing 4 changed files with 259 additions and 52 deletions.
159 changes: 111 additions & 48 deletions api/api.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 18 additions & 1 deletion api/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ message DeleteClientReq {
string id = 1;
}

// DeleteClientResp determines if the.
// DeleteClientResp determines if the client is deleted successfully.
message DeleteClientResp {
bool not_found = 1;
}
Expand Down Expand Up @@ -120,6 +120,19 @@ message ListRefreshResp {
repeated RefreshTokenRef refresh_tokens = 1;
}

// RevokeRefreshReq is a request to revoke the refresh token of the user-client pair.
message RevokeRefreshReq {
// The "sub" claim returned in the ID Token.
string user_id = 1;
string client_id = 2;
}

// RevokeRefreshResp determines if the refresh token is revoked successfully.
message RevokeRefreshResp {
// Set to true is refresh token was not found and token could not be revoked.
bool not_found = 1;
}

// Dex represents the dex gRPC service.
service Dex {
// CreateClient creates a client.
Expand All @@ -138,4 +151,8 @@ service Dex {
rpc GetVersion(VersionReq) returns (VersionResp) {};
// ListRefresh lists all the refresh token entries for a particular user.
rpc ListRefresh(ListRefreshReq) returns (ListRefreshResp) {};
// RevokeRefresh revokes the refresh token for the provided user-client pair.
//
// Note that each user-client pair can have only one refresh token at a time.
rpc RevokeRefresh(RevokeRefreshReq) returns (RevokeRefreshResp) {};
}
42 changes: 39 additions & 3 deletions server/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (

// apiVersion increases every time a new call is added to the API. Clients should use this info
// to determine if the server supports specific features.
const apiVersion = 0
const apiVersion = 1

// NewAPI returns a server which implements the gRPC API interface.
func NewAPI(s storage.Storage, logger logrus.FieldLogger) api.DexServer {
Expand Down Expand Up @@ -204,13 +204,13 @@ func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.
id := new(internal.IDTokenSubject)
if err := internal.Unmarshal(req.UserId, id); err != nil {
d.logger.Errorf("api: failed to unmarshal ID Token subject: %v", err)
return nil, fmt.Errorf("unmarshal ID Token subject: %v", err)
return nil, err
}

offlineSessions, err := d.s.GetOfflineSessions(id.UserId, id.ConnId)
if err != nil {
d.logger.Errorf("api: failed to list refresh tokens: %v", err)
return nil, fmt.Errorf("list refresh tokens: %v", err)
return nil, err
}

var refreshTokenRefs []*api.RefreshTokenRef
Expand All @@ -228,3 +228,39 @@ func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.
RefreshTokens: refreshTokenRefs,
}, nil
}

func (d dexAPI) RevokeRefresh(ctx context.Context, req *api.RevokeRefreshReq) (*api.RevokeRefreshResp, error) {
id := new(internal.IDTokenSubject)
if err := internal.Unmarshal(req.UserId, id); err != nil {
d.logger.Errorf("api: failed to unmarshal ID Token subject: %v", err)
return nil, err
}

var refreshID string
updater := func(old storage.OfflineSessions) (storage.OfflineSessions, error) {
if refreshID = old.Refresh[req.ClientId].ID; refreshID == "" {
return old, fmt.Errorf("user does not have a refresh token for the client = %s", req.ClientId)
}

// Remove entry from Refresh list of the OfflineSession object.
delete(old.Refresh, req.ClientId)

return old, nil
}

if err := d.s.UpdateOfflineSessions(id.UserId, id.ConnId, updater); err != nil {
if err == storage.ErrNotFound {
return &api.RevokeRefreshResp{NotFound: true}, nil
}
d.logger.Errorf("api: failed to update offline session object: %v", err)
return nil, err
}

// Delete the refresh token from the storage
if err := d.s.DeleteRefresh(refreshID); err != nil {
d.logger.Errorf("failed to delete refresh token: %v", err)
return nil, err
}

return &api.RevokeRefreshResp{}, nil
}

0 comments on commit 7e9dc83

Please sign in to comment.