...

Source file src/github.com/ory/fosite/storage/memory.go

Documentation: github.com/ory/fosite/storage

     1  /*
     2   * Copyright © 2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
    17   * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
    18   * @license 	Apache-2.0
    19   *
    20   */
    21  
    22  package storage
    23  
    24  import (
    25  	"context"
    26  	"sync"
    27  	"time"
    28  
    29  	"gopkg.in/square/go-jose.v2"
    30  
    31  	"github.com/ory/fosite"
    32  )
    33  
    34  type MemoryUserRelation struct {
    35  	Username string
    36  	Password string
    37  }
    38  
    39  type IssuerPublicKeys struct {
    40  	Issuer    string
    41  	KeysBySub map[string]SubjectPublicKeys
    42  }
    43  
    44  type SubjectPublicKeys struct {
    45  	Subject string
    46  	Keys    map[string]PublicKeyScopes
    47  }
    48  
    49  type PublicKeyScopes struct {
    50  	Key    *jose.JSONWebKey
    51  	Scopes []string
    52  }
    53  
    54  type MemoryStore struct {
    55  	Clients         map[string]fosite.Client
    56  	AuthorizeCodes  map[string]StoreAuthorizeCode
    57  	IDSessions      map[string]fosite.Requester
    58  	AccessTokens    map[string]fosite.Requester
    59  	RefreshTokens   map[string]StoreRefreshToken
    60  	PKCES           map[string]fosite.Requester
    61  	Users           map[string]MemoryUserRelation
    62  	BlacklistedJTIs map[string]time.Time
    63  	// In-memory request ID to token signatures
    64  	AccessTokenRequestIDs  map[string]string
    65  	RefreshTokenRequestIDs map[string]string
    66  	// Public keys to check signature in auth grant jwt assertion.
    67  	IssuerPublicKeys map[string]IssuerPublicKeys
    68  
    69  	clientsMutex                sync.RWMutex
    70  	authorizeCodesMutex         sync.RWMutex
    71  	idSessionsMutex             sync.RWMutex
    72  	accessTokensMutex           sync.RWMutex
    73  	refreshTokensMutex          sync.RWMutex
    74  	pkcesMutex                  sync.RWMutex
    75  	usersMutex                  sync.RWMutex
    76  	blacklistedJTIsMutex        sync.RWMutex
    77  	accessTokenRequestIDsMutex  sync.RWMutex
    78  	refreshTokenRequestIDsMutex sync.RWMutex
    79  	issuerPublicKeysMutex       sync.RWMutex
    80  }
    81  
    82  func NewMemoryStore() *MemoryStore {
    83  	return &MemoryStore{
    84  		Clients:                make(map[string]fosite.Client),
    85  		AuthorizeCodes:         make(map[string]StoreAuthorizeCode),
    86  		IDSessions:             make(map[string]fosite.Requester),
    87  		AccessTokens:           make(map[string]fosite.Requester),
    88  		RefreshTokens:          make(map[string]StoreRefreshToken),
    89  		PKCES:                  make(map[string]fosite.Requester),
    90  		Users:                  make(map[string]MemoryUserRelation),
    91  		AccessTokenRequestIDs:  make(map[string]string),
    92  		RefreshTokenRequestIDs: make(map[string]string),
    93  		BlacklistedJTIs:        make(map[string]time.Time),
    94  		IssuerPublicKeys:       make(map[string]IssuerPublicKeys),
    95  	}
    96  }
    97  
    98  type StoreAuthorizeCode struct {
    99  	active bool
   100  	fosite.Requester
   101  }
   102  
   103  type StoreRefreshToken struct {
   104  	active bool
   105  	fosite.Requester
   106  }
   107  
   108  func NewExampleStore() *MemoryStore {
   109  	return &MemoryStore{
   110  		IDSessions: make(map[string]fosite.Requester),
   111  		Clients: map[string]fosite.Client{
   112  			"my-client": &fosite.DefaultClient{
   113  				ID:             "my-client",
   114  				Secret:         []byte(`$2a$10$IxMdI6d.LIRZPpSfEwNoeu4rY3FhDREsxFJXikcgdRRAStxUlsuEO`),            // = "foobar"
   115  				RotatedSecrets: [][]byte{[]byte(`$2y$10$X51gLxUQJ.hGw1epgHTE5u0bt64xM0COU7K9iAp.OFg8p2pUd.1zC `)}, // = "foobaz",
   116  				RedirectURIs:   []string{"http://localhost:3846/callback"},
   117  				ResponseTypes:  []string{"id_token", "code", "token", "id_token token", "code id_token", "code token", "code id_token token"},
   118  				GrantTypes:     []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"},
   119  				Scopes:         []string{"fosite", "openid", "photos", "offline"},
   120  			},
   121  			"encoded:client": &fosite.DefaultClient{
   122  				ID:             "encoded:client",
   123  				Secret:         []byte(`$2a$10$A7M8b65dSSKGHF0H2sNkn.9Z0hT8U1Nv6OWPV3teUUaczXkVkxuDS`), // = "encoded&password"
   124  				RotatedSecrets: nil,
   125  				RedirectURIs:   []string{"http://localhost:3846/callback"},
   126  				ResponseTypes:  []string{"id_token", "code", "token", "id_token token", "code id_token", "code token", "code id_token token"},
   127  				GrantTypes:     []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"},
   128  				Scopes:         []string{"fosite", "openid", "photos", "offline"},
   129  			},
   130  		},
   131  		Users: map[string]MemoryUserRelation{
   132  			"peter": {
   133  				// This store simply checks for equality, a real storage implementation would obviously use
   134  				// a hashing algorithm for encrypting the user password.
   135  				Username: "peter",
   136  				Password: "secret",
   137  			},
   138  		},
   139  		AuthorizeCodes:         map[string]StoreAuthorizeCode{},
   140  		AccessTokens:           map[string]fosite.Requester{},
   141  		RefreshTokens:          map[string]StoreRefreshToken{},
   142  		PKCES:                  map[string]fosite.Requester{},
   143  		AccessTokenRequestIDs:  map[string]string{},
   144  		RefreshTokenRequestIDs: map[string]string{},
   145  		IssuerPublicKeys:       map[string]IssuerPublicKeys{},
   146  	}
   147  }
   148  
   149  func (s *MemoryStore) CreateOpenIDConnectSession(_ context.Context, authorizeCode string, requester fosite.Requester) error {
   150  	s.idSessionsMutex.Lock()
   151  	defer s.idSessionsMutex.Unlock()
   152  
   153  	s.IDSessions[authorizeCode] = requester
   154  	return nil
   155  }
   156  
   157  func (s *MemoryStore) GetOpenIDConnectSession(_ context.Context, authorizeCode string, requester fosite.Requester) (fosite.Requester, error) {
   158  	s.idSessionsMutex.RLock()
   159  	defer s.idSessionsMutex.RUnlock()
   160  
   161  	cl, ok := s.IDSessions[authorizeCode]
   162  	if !ok {
   163  		return nil, fosite.ErrNotFound
   164  	}
   165  	return cl, nil
   166  }
   167  
   168  // DeleteOpenIDConnectSession is not really called from anywhere and it is deprecated.
   169  func (s *MemoryStore) DeleteOpenIDConnectSession(_ context.Context, authorizeCode string) error {
   170  	s.idSessionsMutex.Lock()
   171  	defer s.idSessionsMutex.Unlock()
   172  
   173  	delete(s.IDSessions, authorizeCode)
   174  	return nil
   175  }
   176  
   177  func (s *MemoryStore) GetClient(_ context.Context, id string) (fosite.Client, error) {
   178  	s.clientsMutex.RLock()
   179  	defer s.clientsMutex.RUnlock()
   180  
   181  	cl, ok := s.Clients[id]
   182  	if !ok {
   183  		return nil, fosite.ErrNotFound
   184  	}
   185  	return cl, nil
   186  }
   187  
   188  func (s *MemoryStore) ClientAssertionJWTValid(_ context.Context, jti string) error {
   189  	s.blacklistedJTIsMutex.RLock()
   190  	defer s.blacklistedJTIsMutex.RUnlock()
   191  
   192  	if exp, exists := s.BlacklistedJTIs[jti]; exists && exp.After(time.Now()) {
   193  		return fosite.ErrJTIKnown
   194  	}
   195  
   196  	return nil
   197  }
   198  
   199  func (s *MemoryStore) SetClientAssertionJWT(_ context.Context, jti string, exp time.Time) error {
   200  	s.blacklistedJTIsMutex.Lock()
   201  	defer s.blacklistedJTIsMutex.Unlock()
   202  
   203  	// delete expired jtis
   204  	for j, e := range s.BlacklistedJTIs {
   205  		if e.Before(time.Now()) {
   206  			delete(s.BlacklistedJTIs, j)
   207  		}
   208  	}
   209  
   210  	if _, exists := s.BlacklistedJTIs[jti]; exists {
   211  		return fosite.ErrJTIKnown
   212  	}
   213  
   214  	s.BlacklistedJTIs[jti] = exp
   215  	return nil
   216  }
   217  
   218  func (s *MemoryStore) CreateAuthorizeCodeSession(_ context.Context, code string, req fosite.Requester) error {
   219  	s.authorizeCodesMutex.Lock()
   220  	defer s.authorizeCodesMutex.Unlock()
   221  
   222  	s.AuthorizeCodes[code] = StoreAuthorizeCode{active: true, Requester: req}
   223  	return nil
   224  }
   225  
   226  func (s *MemoryStore) GetAuthorizeCodeSession(_ context.Context, code string, _ fosite.Session) (fosite.Requester, error) {
   227  	s.authorizeCodesMutex.RLock()
   228  	defer s.authorizeCodesMutex.RUnlock()
   229  
   230  	rel, ok := s.AuthorizeCodes[code]
   231  	if !ok {
   232  		return nil, fosite.ErrNotFound
   233  	}
   234  	if !rel.active {
   235  		return rel, fosite.ErrInvalidatedAuthorizeCode
   236  	}
   237  
   238  	return rel.Requester, nil
   239  }
   240  
   241  func (s *MemoryStore) InvalidateAuthorizeCodeSession(ctx context.Context, code string) error {
   242  	s.authorizeCodesMutex.Lock()
   243  	defer s.authorizeCodesMutex.Unlock()
   244  
   245  	rel, ok := s.AuthorizeCodes[code]
   246  	if !ok {
   247  		return fosite.ErrNotFound
   248  	}
   249  	rel.active = false
   250  	s.AuthorizeCodes[code] = rel
   251  	return nil
   252  }
   253  
   254  func (s *MemoryStore) CreatePKCERequestSession(_ context.Context, code string, req fosite.Requester) error {
   255  	s.pkcesMutex.Lock()
   256  	defer s.pkcesMutex.Unlock()
   257  
   258  	s.PKCES[code] = req
   259  	return nil
   260  }
   261  
   262  func (s *MemoryStore) GetPKCERequestSession(_ context.Context, code string, _ fosite.Session) (fosite.Requester, error) {
   263  	s.pkcesMutex.RLock()
   264  	defer s.pkcesMutex.RUnlock()
   265  
   266  	rel, ok := s.PKCES[code]
   267  	if !ok {
   268  		return nil, fosite.ErrNotFound
   269  	}
   270  	return rel, nil
   271  }
   272  
   273  func (s *MemoryStore) DeletePKCERequestSession(_ context.Context, code string) error {
   274  	s.pkcesMutex.Lock()
   275  	defer s.pkcesMutex.Unlock()
   276  
   277  	delete(s.PKCES, code)
   278  	return nil
   279  }
   280  
   281  func (s *MemoryStore) CreateAccessTokenSession(_ context.Context, signature string, req fosite.Requester) error {
   282  	// We first lock accessTokenRequestIDsMutex and then accessTokensMutex because this is the same order
   283  	// locking happens in RevokeAccessToken and using the same order prevents deadlocks.
   284  	s.accessTokenRequestIDsMutex.Lock()
   285  	defer s.accessTokenRequestIDsMutex.Unlock()
   286  	s.accessTokensMutex.Lock()
   287  	defer s.accessTokensMutex.Unlock()
   288  
   289  	s.AccessTokens[signature] = req
   290  	s.AccessTokenRequestIDs[req.GetID()] = signature
   291  	return nil
   292  }
   293  
   294  func (s *MemoryStore) GetAccessTokenSession(_ context.Context, signature string, _ fosite.Session) (fosite.Requester, error) {
   295  	s.accessTokensMutex.RLock()
   296  	defer s.accessTokensMutex.RUnlock()
   297  
   298  	rel, ok := s.AccessTokens[signature]
   299  	if !ok {
   300  		return nil, fosite.ErrNotFound
   301  	}
   302  	return rel, nil
   303  }
   304  
   305  func (s *MemoryStore) DeleteAccessTokenSession(_ context.Context, signature string) error {
   306  	s.accessTokensMutex.Lock()
   307  	defer s.accessTokensMutex.Unlock()
   308  
   309  	delete(s.AccessTokens, signature)
   310  	return nil
   311  }
   312  
   313  func (s *MemoryStore) CreateRefreshTokenSession(_ context.Context, signature string, req fosite.Requester) error {
   314  	// We first lock refreshTokenRequestIDsMutex and then refreshTokensMutex because this is the same order
   315  	// locking happens in RevokeRefreshToken and using the same order prevents deadlocks.
   316  	s.refreshTokenRequestIDsMutex.Lock()
   317  	defer s.refreshTokenRequestIDsMutex.Unlock()
   318  	s.refreshTokensMutex.Lock()
   319  	defer s.refreshTokensMutex.Unlock()
   320  
   321  	s.RefreshTokens[signature] = StoreRefreshToken{active: true, Requester: req}
   322  	s.RefreshTokenRequestIDs[req.GetID()] = signature
   323  	return nil
   324  }
   325  
   326  func (s *MemoryStore) GetRefreshTokenSession(_ context.Context, signature string, _ fosite.Session) (fosite.Requester, error) {
   327  	s.refreshTokensMutex.RLock()
   328  	defer s.refreshTokensMutex.RUnlock()
   329  
   330  	rel, ok := s.RefreshTokens[signature]
   331  	if !ok {
   332  		return nil, fosite.ErrNotFound
   333  	}
   334  	if !rel.active {
   335  		return rel, fosite.ErrInactiveToken
   336  	}
   337  	return rel, nil
   338  }
   339  
   340  func (s *MemoryStore) DeleteRefreshTokenSession(_ context.Context, signature string) error {
   341  	s.refreshTokensMutex.Lock()
   342  	defer s.refreshTokensMutex.Unlock()
   343  
   344  	delete(s.RefreshTokens, signature)
   345  	return nil
   346  }
   347  
   348  func (s *MemoryStore) Authenticate(_ context.Context, name string, secret string) error {
   349  	s.usersMutex.RLock()
   350  	defer s.usersMutex.RUnlock()
   351  
   352  	rel, ok := s.Users[name]
   353  	if !ok {
   354  		return fosite.ErrNotFound
   355  	}
   356  	if rel.Password != secret {
   357  		return fosite.ErrNotFound.WithDebug("Invalid credentials")
   358  	}
   359  	return nil
   360  }
   361  
   362  func (s *MemoryStore) RevokeRefreshToken(ctx context.Context, requestID string) error {
   363  	s.refreshTokenRequestIDsMutex.Lock()
   364  	defer s.refreshTokenRequestIDsMutex.Unlock()
   365  
   366  	if signature, exists := s.RefreshTokenRequestIDs[requestID]; exists {
   367  		rel, ok := s.RefreshTokens[signature]
   368  		if !ok {
   369  			return fosite.ErrNotFound
   370  		}
   371  		rel.active = false
   372  		s.RefreshTokens[signature] = rel
   373  	}
   374  	return nil
   375  }
   376  
   377  func (s *MemoryStore) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) error {
   378  	// no configuration option is available; grace period is not available with memory store
   379  	return s.RevokeRefreshToken(ctx, requestID)
   380  }
   381  
   382  func (s *MemoryStore) RevokeAccessToken(ctx context.Context, requestID string) error {
   383  	s.accessTokenRequestIDsMutex.RLock()
   384  	defer s.accessTokenRequestIDsMutex.RUnlock()
   385  
   386  	if signature, exists := s.AccessTokenRequestIDs[requestID]; exists {
   387  		if err := s.DeleteAccessTokenSession(ctx, signature); err != nil {
   388  			return err
   389  		}
   390  	}
   391  	return nil
   392  }
   393  
   394  func (s *MemoryStore) GetPublicKey(ctx context.Context, issuer string, subject string, keyId string) (*jose.JSONWebKey, error) {
   395  	s.issuerPublicKeysMutex.RLock()
   396  	defer s.issuerPublicKeysMutex.RUnlock()
   397  
   398  	if issuerKeys, ok := s.IssuerPublicKeys[issuer]; ok {
   399  		if subKeys, ok := issuerKeys.KeysBySub[subject]; ok {
   400  			if keyScopes, ok := subKeys.Keys[keyId]; ok {
   401  				return keyScopes.Key, nil
   402  			}
   403  		}
   404  	}
   405  
   406  	return nil, fosite.ErrNotFound
   407  }
   408  func (s *MemoryStore) GetPublicKeys(ctx context.Context, issuer string, subject string) (*jose.JSONWebKeySet, error) {
   409  	s.issuerPublicKeysMutex.RLock()
   410  	defer s.issuerPublicKeysMutex.RUnlock()
   411  
   412  	if issuerKeys, ok := s.IssuerPublicKeys[issuer]; ok {
   413  		if subKeys, ok := issuerKeys.KeysBySub[subject]; ok {
   414  			if len(subKeys.Keys) == 0 {
   415  				return nil, fosite.ErrNotFound
   416  			}
   417  
   418  			keys := make([]jose.JSONWebKey, 0, len(subKeys.Keys))
   419  			for _, keyScopes := range subKeys.Keys {
   420  				keys = append(keys, *keyScopes.Key)
   421  			}
   422  
   423  			return &jose.JSONWebKeySet{Keys: keys}, nil
   424  		}
   425  	}
   426  
   427  	return nil, fosite.ErrNotFound
   428  }
   429  
   430  func (s *MemoryStore) GetPublicKeyScopes(ctx context.Context, issuer string, subject string, keyId string) ([]string, error) {
   431  	s.issuerPublicKeysMutex.RLock()
   432  	defer s.issuerPublicKeysMutex.RUnlock()
   433  
   434  	if issuerKeys, ok := s.IssuerPublicKeys[issuer]; ok {
   435  		if subKeys, ok := issuerKeys.KeysBySub[subject]; ok {
   436  			if keyScopes, ok := subKeys.Keys[keyId]; ok {
   437  				return keyScopes.Scopes, nil
   438  			}
   439  		}
   440  	}
   441  
   442  	return nil, fosite.ErrNotFound
   443  }
   444  
   445  func (s *MemoryStore) IsJWTUsed(ctx context.Context, jti string) (bool, error) {
   446  	err := s.ClientAssertionJWTValid(ctx, jti)
   447  	if err != nil {
   448  		return true, nil
   449  	}
   450  
   451  	return false, nil
   452  }
   453  
   454  func (s *MemoryStore) MarkJWTUsedForTime(ctx context.Context, jti string, exp time.Time) error {
   455  	return s.SetClientAssertionJWT(ctx, jti, exp)
   456  }
   457  

View as plain text