Beispiel #1
0
func (s *Server) RefreshToken(creds oidc.ClientCredentials, scopes scope.Scopes, token string) (*jose.JWT, error) {
	ok, err := s.ClientManager.Authenticate(creds)
	if err != nil {
		log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}
	if !ok {
		log.Errorf("Failed to Authenticate client %s", creds.ID)
		return nil, oauth2.NewError(oauth2.ErrorInvalidClient)
	}

	userID, rtScopes, err := s.RefreshTokenRepo.Verify(creds.ID, token)
	switch err {
	case nil:
		break
	case refresh.ErrorInvalidToken:
		return nil, oauth2.NewError(oauth2.ErrorInvalidRequest)
	case refresh.ErrorInvalidClientID:
		return nil, oauth2.NewError(oauth2.ErrorInvalidClient)
	default:
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	if len(scopes) == 0 {
		scopes = rtScopes
	} else {
		if !rtScopes.Contains(scopes) {
			return nil, oauth2.NewError(oauth2.ErrorInvalidRequest)
		}
	}

	user, err := s.UserRepo.Get(nil, userID)
	if err != nil {
		// The error can be user.ErrorNotFound, but we are not deleting
		// user at this moment, so this shouldn't happen.
		log.Errorf("Failed to fetch user %q from repo: %v: ", userID, err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	signer, err := s.KeyManager.Signer()
	if err != nil {
		log.Errorf("Failed to refresh ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	now := time.Now()
	expireAt := now.Add(session.DefaultSessionValidityWindow)

	claims := oidc.NewClaims(s.IssuerURL.String(), user.ID, creds.ID, now, expireAt)
	user.AddToClaims(claims)

	s.addClaimsFromScope(claims, scope.Scopes(scopes), creds.ID)

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("Failed to generate ID token: %v", err)
		return nil, oauth2.NewError(oauth2.ErrorServerError)
	}

	log.Infof("New token sent: clientID=%s", creds.ID)

	return jwt, nil
}
Beispiel #2
0
func (s *Server) RefreshToken(creds oidc.ClientCredentials, scopes scope.Scopes, token string) (*jose.JWT, string, time.Time, error) {
	ok, err := s.ClientManager.Authenticate(creds)
	if err != nil {
		log.Errorf("Failed fetching client %s from repo: %v", creds.ID, err)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}
	if !ok {
		log.Errorf("Failed to Authenticate client %s", creds.ID)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidClient)
	}

	userID, connectorID, rtScopes, err := s.RefreshTokenRepo.Verify(creds.ID, token)
	switch err {
	case nil:
		break
	case refresh.ErrorInvalidToken:
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidRequest)
	case refresh.ErrorInvalidClientID:
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidClient)
	default:
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}

	if len(scopes) == 0 {
		scopes = rtScopes
	} else {
		if !rtScopes.Contains(scopes) {
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorInvalidRequest)
		}
	}

	usr, err := s.UserRepo.Get(nil, userID)
	if err != nil {
		// The error can be user.ErrorNotFound, but we are not deleting
		// user at this moment, so this shouldn't happen.
		log.Errorf("Failed to fetch user %q from repo: %v: ", userID, err)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}

	var groups []string
	if rtScopes.HasScope(scope.ScopeGroups) {
		conn, ok := s.connector(connectorID)
		if !ok {
			log.Errorf("refresh token contained invalid connector ID (%s)", connectorID)
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
		}

		grouper, ok := conn.(connector.GroupsConnector)
		if !ok {
			log.Errorf("refresh token requested groups for connector (%s) that doesn't support groups", connectorID)
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
		}

		remoteIdentities, err := s.UserRepo.GetRemoteIdentities(nil, userID)
		if err != nil {
			log.Errorf("failed to get remote identities: %v", err)
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
		}
		remoteIdentity, ok := func() (user.RemoteIdentity, bool) {
			for _, ri := range remoteIdentities {
				if ri.ConnectorID == connectorID {
					return ri, true
				}
			}
			return user.RemoteIdentity{}, false
		}()
		if !ok {
			log.Errorf("failed to get remote identity for connector %s", connectorID)
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
		}
		if groups, err = grouper.Groups(remoteIdentity.ID); err != nil {
			log.Errorf("failed to get groups for refresh token: %v", connectorID)
			return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
		}
	}

	signer, err := s.KeyManager.Signer()
	if err != nil {
		log.Errorf("Failed to refresh ID token: %v", err)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}

	now := time.Now()
	expiresAt := now.Add(session.DefaultSessionValidityWindow)

	claims := oidc.NewClaims(s.IssuerURL.String(), usr.ID, creds.ID, now, expiresAt)
	usr.AddToClaims(claims)
	if rtScopes.HasScope(scope.ScopeGroups) {
		if groups == nil {
			groups = []string{}
		}
		claims["groups"] = groups
	}

	s.addClaimsFromScope(claims, scope.Scopes(scopes), creds.ID)

	jwt, err := jose.NewSignedJWT(claims, signer)
	if err != nil {
		log.Errorf("Failed to generate ID token: %v", err)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}

	refreshToken, err := s.RefreshTokenRepo.RenewRefreshToken(creds.ID, userID, token)
	if err != nil {
		log.Errorf("Failed to generate new refresh token: %v", err)
		return nil, "", time.Time{}, oauth2.NewError(oauth2.ErrorServerError)
	}

	log.Infof("New token sent: clientID=%s", creds.ID)

	return jwt, refreshToken, expiresAt, nil
}