Commit b119ffdd authored by rithu leena john's avatar rithu leena john Committed by GitHub

Merge pull request #801 from rithujohn191/token-revocation

api: adding a gRPC call for listing refresh tokens.
parents 53e38367 d201e492
This diff is collapsed.
......@@ -83,7 +83,7 @@ message DeletePasswordResp {
// ListPasswordReq is a request to enumerate passwords.
message ListPasswordReq {}
// ListPasswordResp returs a list of passwords.
// ListPasswordResp returns a list of passwords.
message ListPasswordResp {
repeated Password passwords = 1;
}
......@@ -100,6 +100,26 @@ message VersionResp {
int32 api = 2;
}
// RefreshTokenRef contains the metadata for a refresh token that is managed by the storage.
message RefreshTokenRef {
// ID of the refresh token.
string id = 1;
string client_id = 2;
string created_at = 3;
string last_used = 4;
}
// ListRefreshReq is a request to enumerate the refresh tokens of a user.
message ListRefreshReq {
// The "sub" claim returned in the ID Token.
string user_id = 1;
}
// ListRefreshResp returns a list of refresh tokens for a user.
message ListRefreshResp {
repeated RefreshTokenRef refresh_tokens = 1;
}
// Dex represents the dex gRPC service.
service Dex {
// CreateClient creates a client.
......@@ -116,4 +136,6 @@ service Dex {
rpc ListPasswords(ListPasswordReq) returns (ListPasswordResp) {};
// GetVersion returns version information of the server.
rpc GetVersion(VersionReq) returns (VersionResp) {};
// ListRefresh lists all the refresh token entries for a particular user.
rpc ListRefresh(ListRefreshReq) returns (ListRefreshResp) {};
}
......@@ -9,6 +9,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/coreos/dex/api"
"github.com/coreos/dex/server/internal"
"github.com/coreos/dex/storage"
"github.com/coreos/dex/version"
)
......@@ -198,3 +199,32 @@ func (d dexAPI) ListPasswords(ctx context.Context, req *api.ListPasswordReq) (*a
}, nil
}
func (d dexAPI) ListRefresh(ctx context.Context, req *api.ListRefreshReq) (*api.ListRefreshResp, 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, fmt.Errorf("unmarshal ID Token subject: %v", 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)
}
var refreshTokenRefs []*api.RefreshTokenRef
for _, session := range offlineSessions.Refresh {
r := api.RefreshTokenRef{
Id: session.ID,
ClientId: session.ClientID,
CreatedAt: session.CreatedAt.String(),
LastUsed: session.LastUsed.String(),
}
refreshTokenRefs = append(refreshTokenRefs, &r)
}
return &api.ListRefreshResp{
RefreshTokens: refreshTokenRefs,
}, nil
}
......@@ -510,7 +510,7 @@ func (s *Server) sendCodeResponse(w http.ResponseWriter, r *http.Request, authRe
case responseTypeIDToken:
implicitOrHybrid = true
var err error
idToken, idTokenExpiry, err = s.newIDToken(authReq.ClientID, authReq.Claims, authReq.Scopes, authReq.Nonce, accessToken)
idToken, idTokenExpiry, err = s.newIDToken(authReq.ClientID, authReq.Claims, authReq.Scopes, authReq.Nonce, accessToken, authReq.ConnectorID)
if err != nil {
s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
......@@ -632,7 +632,7 @@ func (s *Server) handleAuthCode(w http.ResponseWriter, r *http.Request, client s
}
accessToken := storage.NewID()
idToken, expiry, err := s.newIDToken(client.ID, authCode.Claims, authCode.Scopes, authCode.Nonce, accessToken)
idToken, expiry, err := s.newIDToken(client.ID, authCode.Claims, authCode.Scopes, authCode.Nonce, accessToken, authCode.ConnectorID)
if err != nil {
s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
......@@ -866,7 +866,7 @@ func (s *Server) handleRefreshToken(w http.ResponseWriter, r *http.Request, clie
}
accessToken := storage.NewID()
idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, refresh.Nonce, accessToken)
idToken, expiry, err := s.newIDToken(client.ID, claims, scopes, refresh.Nonce, accessToken, refresh.ConnectorID)
if err != nil {
s.logger.Errorf("failed to create ID token: %v", err)
s.tokenErrHelper(w, errServerError, "", http.StatusInternalServerError)
......
......@@ -12,6 +12,7 @@ It is generated from these files:
It has these top-level messages:
RefreshToken
IDTokenSubject
*/
package internal
......@@ -41,19 +42,35 @@ func (m *RefreshToken) String() string { return proto.CompactTextStri
func (*RefreshToken) ProtoMessage() {}
func (*RefreshToken) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
// IDTokenSubject represents both the userID and connID which is returned
// as the "sub" claim in the ID Token.
type IDTokenSubject struct {
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId" json:"user_id,omitempty"`
ConnId string `protobuf:"bytes,2,opt,name=conn_id,json=connId" json:"conn_id,omitempty"`
}
func (m *IDTokenSubject) Reset() { *m = IDTokenSubject{} }
func (m *IDTokenSubject) String() string { return proto.CompactTextString(m) }
func (*IDTokenSubject) ProtoMessage() {}
func (*IDTokenSubject) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func init() {
proto.RegisterType((*RefreshToken)(nil), "internal.RefreshToken")
proto.RegisterType((*IDTokenSubject)(nil), "internal.IDTokenSubject")
}
func init() { proto.RegisterFile("server/internal/types.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 112 bytes of a gzipped FileDescriptorProto
// 157 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0x92, 0x2e, 0x4e, 0x2d, 0x2a,
0x4b, 0x2d, 0xd2, 0xcf, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x2f, 0xa9, 0x2c, 0x48,
0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x80, 0x89, 0x2a, 0x39, 0x73, 0xf1, 0x04,
0xa5, 0xa6, 0x15, 0xa5, 0x16, 0x67, 0x84, 0xe4, 0x67, 0xa7, 0xe6, 0x09, 0xc9, 0x72, 0x71, 0x15,
0x41, 0xf8, 0xf1, 0x99, 0x29, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x9c, 0x50, 0x11, 0xcf,
0x14, 0x21, 0x11, 0x2e, 0xd6, 0x12, 0x90, 0x3a, 0x09, 0x26, 0xb0, 0x0c, 0x84, 0x93, 0xc4, 0x06,
0x36, 0xd5, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x9b, 0xd0, 0x5a, 0x1d, 0x74, 0x00, 0x00, 0x00,
0x14, 0x21, 0x11, 0x2e, 0xd6, 0x12, 0x90, 0x3a, 0x09, 0x26, 0xb0, 0x0c, 0x84, 0xa3, 0xe4, 0xc4,
0xc5, 0xe7, 0xe9, 0x02, 0xd6, 0x1f, 0x5c, 0x9a, 0x94, 0x95, 0x9a, 0x5c, 0x22, 0x24, 0xce, 0xc5,
0x5e, 0x5a, 0x9c, 0x5a, 0x84, 0x30, 0x83, 0x0d, 0xc4, 0xf5, 0x4c, 0x01, 0x49, 0x24, 0xe7, 0xe7,
0xe5, 0x81, 0x24, 0x20, 0x46, 0xb0, 0x81, 0xb8, 0x9e, 0x29, 0x49, 0x6c, 0x60, 0x97, 0x19, 0x03,
0x02, 0x00, 0x00, 0xff, 0xff, 0x13, 0xfe, 0x01, 0x37, 0xb8, 0x00, 0x00, 0x00,
}
......@@ -8,3 +8,10 @@ message RefreshToken {
string refresh_id = 1;
string token = 2;
}
// IDTokenSubject represents both the userID and connID which is returned
// as the "sub" claim in the ID Token.
message IDTokenSubject {
string user_id = 1;
string conn_id = 2;
}
......@@ -21,6 +21,7 @@ import (
jose "gopkg.in/square/go-jose.v2"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/server/internal"
"github.com/coreos/dex/storage"
)
......@@ -246,7 +247,7 @@ type idTokenClaims struct {
Name string `json:"name,omitempty"`
}
func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken string) (idToken string, expiry time.Time, err error) {
func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []string, nonce, accessToken, connID string) (idToken string, expiry time.Time, err error) {
keys, err := s.storage.GetKeys()
if err != nil {
s.logger.Errorf("Failed to get keys: %v", err)
......@@ -265,9 +266,20 @@ func (s *Server) newIDToken(clientID string, claims storage.Claims, scopes []str
issuedAt := s.now()
expiry = issuedAt.Add(s.idTokensValidFor)
sub := &internal.IDTokenSubject{
UserId: claims.UserID,
ConnId: connID,
}
subjectString, err := internal.Marshal(sub)
if err != nil {
s.logger.Errorf("failed to marshal offline session ID: %v", err)
return "", expiry, fmt.Errorf("failed to marshal offline session ID: %v", err)
}
tok := idTokenClaims{
Issuer: s.issuerURL.String(),
Subject: claims.UserID,
Subject: subjectString,
Nonce: nonce,
Expiry: expiry.Unix(),
IssuedAt: issuedAt.Unix(),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment