Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
GGCE
GGCE Server
Commits
90723e9a
Commit
90723e9a
authored
Feb 22, 2021
by
Maxym Borodenko
Committed by
Matija Obreza
Feb 28, 2021
Browse files
OAuth token repository
parent
38a55028
Changes
14
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/gringlobal/api/ApiExceptionHandler.java
View file @
90723e9a
...
...
@@ -26,6 +26,7 @@ import org.genesys.blocks.security.NotUniqueUserException;
import
org.genesys.filerepository.FileRepositoryException
;
import
org.genesys.filerepository.NoSuchRepositoryFileException
;
import
org.genesys.filerepository.NoSuchRepositoryFolderException
;
import
org.gringlobal.service.JPATokenStore
;
import
org.hibernate.hql.internal.ast.InvalidPathException
;
import
org.hibernate.hql.internal.ast.QuerySyntaxException
;
import
org.slf4j.Logger
;
...
...
@@ -169,7 +170,7 @@ public class ApiExceptionHandler {
* @return the api error
*/
@ResponseStatus
(
code
=
HttpStatus
.
NOT_FOUND
)
@ExceptionHandler
(
value
=
{
EntityNotFoundException
.
class
,
NotFoundElement
.
class
,
NoSuchRepositoryFileException
.
class
,
NoSuchRepositoryFolderException
.
class
,
NoUserFoundException
.
class
})
@ExceptionHandler
(
value
=
{
EntityNotFoundException
.
class
,
NotFoundElement
.
class
,
NoSuchRepositoryFileException
.
class
,
NoSuchRepositoryFolderException
.
class
,
NoUserFoundException
.
class
,
JPATokenStore
.
NoSuchTokenException
.
class
})
@ResponseBody
public
ApiError
<
Exception
>
handleNotFound
(
final
Exception
e
,
final
HttpServletRequest
request
)
{
LOG
.
warn
(
"Element not found {} {}"
,
request
.
getMethod
(),
request
.
getRequestURL
());
...
...
src/main/java/org/gringlobal/api/v1/impl/OAuthTokenManagementController.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.api.v1.impl
;
import
java.util.List
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
org.gringlobal.api.v1.ApiBaseController
;
import
org.gringlobal.api.v1.FilteredPage
;
import
org.gringlobal.api.v1.Pagination
;
import
org.gringlobal.model.jwt.AccessToken
;
import
org.gringlobal.model.jwt.RefreshToken
;
import
org.gringlobal.service.JPATokenStore
;
import
org.gringlobal.service.filter.OAuthAccessTokenFilter
;
import
org.gringlobal.service.filter.OAuthRefreshTokenFilter
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.domain.Sort
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.web.bind.annotation.DeleteMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* Allow administrators to manage OAuth tokens.
*
* @author Maxym Borodenko
*/
@RestController
(
"oauthTokenManagementApi1"
)
@PreAuthorize
(
"hasRole('ADMINISTRATOR')"
)
@RequestMapping
(
OAuthTokenManagementController
.
CONTROLLER_PATH
)
@Tag
(
name
=
"oauthTokenManagement"
)
public
class
OAuthTokenManagementController
extends
ApiBaseController
{
public
final
static
String
CONTROLLER_PATH
=
ApiBaseController
.
APIv1_ADMIN_BASE
+
"/oauth-token"
;
@Autowired
private
JPATokenStore
tokenStore
;
/**
* List access tokens.
*
* @param page the page
* @param filter the partner filter
* @return the page
*/
@PostMapping
(
value
=
"/list-access-tokens"
)
public
FilteredPage
<
AccessToken
,
OAuthAccessTokenFilter
>
listAccessTokens
(
final
Pagination
page
,
@RequestBody
(
required
=
false
)
OAuthAccessTokenFilter
filter
)
{
return
new
FilteredPage
<>(
filter
,
tokenStore
.
listAccessTokens
(
filter
,
page
.
toPageRequest
(
100
,
Sort
.
Direction
.
ASC
,
"client.clientId"
)));
}
/**
* List refresh tokens.
*
* @param page the page
* @param filter the partner filter
* @return the page
*/
@PostMapping
(
value
=
"/list-refresh-tokens"
)
public
FilteredPage
<
RefreshToken
,
OAuthRefreshTokenFilter
>
listRefreshTokens
(
final
Pagination
page
,
@RequestBody
(
required
=
false
)
OAuthRefreshTokenFilter
filter
)
{
return
new
FilteredPage
<>(
filter
,
tokenStore
.
listRefreshTokens
(
filter
,
page
.
toPageRequest
(
100
,
Sort
.
Direction
.
ASC
,
"client.clientId"
)));
}
/**
* Revoke all access tokens by the filter.
*
* @param filter the filter
* @return list of revoked token
*/
@PostMapping
(
value
=
"/revoke-access-tokens"
)
public
List
<
AccessToken
>
revokeAccessTokens
(
@RequestBody
final
OAuthAccessTokenFilter
filter
)
{
return
tokenStore
.
revokeAllAccessTokens
(
filter
);
}
/**
* Revoke all refresh tokens by the filter.
*
* @param filter the filter
* @return list of revoked token
*/
@PostMapping
(
value
=
"/revoke-refresh-tokens"
)
public
List
<
RefreshToken
>
revokeRefreshTokens
(
@RequestBody
final
OAuthRefreshTokenFilter
filter
)
{
return
tokenStore
.
revokeAllRefreshTokens
(
filter
);
}
/**
* Revoke access token.
*
* @param id the token id
* @return revoked token
*/
@DeleteMapping
(
value
=
"/access-token/{id}"
)
public
AccessToken
revokeAccessToken
(
@PathVariable
(
"id"
)
final
long
id
)
{
return
tokenStore
.
revokeAccessToken
(
tokenStore
.
getAccessTokenById
(
id
));
}
/**
* Revoke refresh token.
*
* @param id the token id
* @return revoked token
*/
@DeleteMapping
(
value
=
"/refresh-token/{id}"
)
public
RefreshToken
revokeRefreshToken
(
@PathVariable
(
"id"
)
final
long
id
)
{
return
tokenStore
.
revokeRefreshToken
(
tokenStore
.
getRefreshTokenById
(
id
));
}
}
src/main/java/org/gringlobal/application/config/OAuth2ServerConfig.java
View file @
90723e9a
...
...
@@ -26,6 +26,7 @@ import org.genesys.blocks.oauth.service.OAuthServiceImpl;
import
org.genesys.blocks.security.component.OAuthClientOriginCheckFilter
;
import
org.gringlobal.custom.security.CustomUserAuthenticationConverter
;
import
org.gringlobal.custom.security.WebUserTokenGranter
;
import
org.gringlobal.service.JPATokenStoreImpl
;
import
org.gringlobal.service.WebUserService
;
import
org.gringlobal.spring.AccessTokenInCookieFilter
;
import
org.gringlobal.spring.CachedInMemoryAuthorizationCodeServices
;
...
...
@@ -64,7 +65,6 @@ import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import
org.springframework.security.oauth2.provider.token.TokenEnhancerChain
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
import
org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter
;
import
org.springframework.security.oauth2.provider.token.store.JwtTokenStore
;
import
org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter
;
import
org.springframework.web.cors.CorsConfiguration
;
import
org.springframework.web.cors.UrlBasedCorsConfigurationSource
;
...
...
@@ -105,7 +105,7 @@ public class OAuth2ServerConfig {
*/
@Bean
public
TokenStore
tokenStore
()
{
return
new
J
wt
TokenStore
(
accessTokenConverter
());
return
new
J
PA
TokenStore
Impl
(
accessTokenConverter
());
}
/**
...
...
src/main/java/org/gringlobal/model/jwt/AccessToken.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.model.jwt
;
import
javax.persistence.Column
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
/**
* OAuth AccessToken.
*/
@Entity
@Table
(
name
=
"oauth_access_token"
)
public
class
AccessToken
extends
Token
{
/** The Constant serialVersionUID. */
private
static
final
long
serialVersionUID
=
6499194247567277729L
;
/** The refresh token JTI. */
@Column
(
name
=
"refresh_token_jti"
)
private
String
refreshTokenJti
;
/**
* Sets the refresh token.
*
* @param refreshToken the new refresh token
*/
public
void
setRefreshTokenJti
(
final
String
refreshToken
)
{
this
.
refreshTokenJti
=
refreshToken
;
}
/**
* Gets the refresh token.
*
* @return the refresh token
*/
public
String
getRefreshTokenJti
()
{
return
refreshTokenJti
;
}
}
src/main/java/org/gringlobal/model/jwt/RefreshToken.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.model.jwt
;
import
javax.persistence.Entity
;
import
javax.persistence.Table
;
/**
* OAuth RefreshToken.
*/
@Entity
@Table
(
name
=
"oauth_refresh_token"
)
public
class
RefreshToken
extends
Token
{
/** The Constant serialVersionUID. */
private
static
final
long
serialVersionUID
=
-
9217916667924105240L
;
}
src/main/java/org/gringlobal/model/jwt/Token.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.model.jwt
;
import
javax.persistence.Column
;
import
javax.persistence.JoinColumn
;
import
javax.persistence.ManyToOne
;
import
javax.persistence.MappedSuperclass
;
import
javax.persistence.Temporal
;
import
javax.persistence.TemporalType
;
import
java.util.Date
;
import
com.fasterxml.jackson.annotation.JsonIdentityReference
;
import
org.genesys.blocks.model.BasicModel
;
import
org.genesys.blocks.oauth.model.OAuthClient
;
@MappedSuperclass
public
abstract
class
Token
extends
BasicModel
{
/** The Constant serialVersionUID. */
private
static
final
long
serialVersionUID
=
-
9113949717132094415L
;
/** The token JTI. */
@Column
(
name
=
"token_jti"
,
length
=
28
,
unique
=
true
,
updatable
=
false
,
nullable
=
false
)
private
String
tokenJti
;
/** The username. */
@Column
(
length
=
100
)
private
String
username
;
/** The OAuth client. */
@ManyToOne
(
cascade
=
{},
optional
=
false
)
@JoinColumn
(
name
=
"client_id"
,
updatable
=
false
)
@JsonIdentityReference
(
alwaysAsId
=
true
)
private
OAuthClient
client
;
/** The expiration. */
@Temporal
(
TemporalType
.
TIMESTAMP
)
private
Date
expiration
;
/** The IP address of a client. */
@Column
(
name
=
"client_ip"
,
length
=
15
)
private
String
clientIp
;
/**
* Gets the IP.
*
* @return the IP
*/
public
String
getClientIp
()
{
return
clientIp
;
}
/**
* Sets the IP.
*
* @param clientIp the new IP
*/
public
void
setClientIp
(
final
String
clientIp
)
{
this
.
clientIp
=
clientIp
;
}
/**
* Gets the token jti.
*
* @return the token jti
*/
public
String
getTokenJti
()
{
return
tokenJti
;
}
/**
* Sets the token jti.
*
* @param tokenJti the new token jti
*/
public
void
setTokenJti
(
String
tokenJti
)
{
this
.
tokenJti
=
tokenJti
;
}
/**
* Get the identifier of the user associated with this refresh token.
*
* @return Usually the UUID of the User
*/
public
String
getUsername
()
{
return
username
;
}
/**
* Sets the username.
*
* @param username the new username
*/
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
/**
* Get the oauth client for which this token is issued.
*
* @return OAuth client
*/
public
OAuthClient
getClient
()
{
return
client
;
}
/**
* Sets the oauth client.
*
* @param client the new client
*/
public
void
setClient
(
final
OAuthClient
client
)
{
this
.
client
=
client
;
}
/**
* Gets the expiration.
*
* @return the expiration
*/
public
Date
getExpiration
()
{
return
expiration
;
}
/**
* Sets the expiration.
*
* @param expiration the new expiration
*/
public
void
setExpiration
(
Date
expiration
)
{
this
.
expiration
=
expiration
;
}
}
src/main/java/org/gringlobal/persistence/jwt/AccessTokenRepository.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.persistence.jwt
;
import
java.util.Date
;
import
java.util.List
;
import
org.genesys.blocks.oauth.model.OAuthClient
;
import
org.gringlobal.model.jwt.AccessToken
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Modifying
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.data.querydsl.QuerydslPredicateExecutor
;
/**
* @author Maxym Borodenko
*/
public
interface
AccessTokenRepository
extends
JpaRepository
<
AccessToken
,
Long
>,
QuerydslPredicateExecutor
<
AccessToken
>
{
/**
* Delete by refresh token.
*
* @param refreshToken the refresh token
*/
@Modifying
@Query
(
"delete from AccessToken at where at.refreshTokenJti = ?1"
)
void
deleteByRefreshToken
(
String
refreshToken
);
/**
* Find by OAuth client.
*
* @param client the client
* @return the list
*/
List
<
AccessToken
>
findByClient
(
OAuthClient
client
);
/**
* Delete by token jti.
*
* @param jti the jti
*/
@Modifying
@Query
(
"delete from AccessToken at where at.tokenJti = ?1"
)
void
deleteByTokenJti
(
String
jti
);
/**
* Find by token jti.
*
* @param tokenJti the token jti
* @return found record
*/
AccessToken
findByTokenJti
(
String
tokenJti
);
/**
* Find by OAuth client and username.
*
* @param client the client
* @param username the username
* @return the list
*/
List
<
AccessToken
>
findByClientAndUsername
(
OAuthClient
client
,
String
username
);
/**
* Find by username.
*
* @param uuid the uuid
* @return the list
*/
List
<
AccessToken
>
findByUsername
(
String
uuid
);
/**
* Delete expired tokens.
*
* @param date the date
*/
@Query
(
"delete from AccessToken at where at.expiration < ?1"
)
@Modifying
int
deleteOlderThan
(
Date
date
);
}
src/main/java/org/gringlobal/persistence/jwt/RefreshTokenRepository.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.persistence.jwt
;
import
java.util.Date
;
import
java.util.List
;
import
org.genesys.blocks.oauth.model.OAuthClient
;
import
org.gringlobal.model.jwt.RefreshToken
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.Modifying
;
import
org.springframework.data.jpa.repository.Query
;
import
org.springframework.data.querydsl.QuerydslPredicateExecutor
;
/**
* @author Maxym Borodenko
*/
public
interface
RefreshTokenRepository
extends
JpaRepository
<
RefreshToken
,
Long
>,
QuerydslPredicateExecutor
<
RefreshToken
>
{
/**
* Find by Oauth client.
*
* @param client the client
* @return the list
*/
List
<
RefreshToken
>
findByClient
(
OAuthClient
client
);
/**
* Delete by token jti.
*
* @param jti the jti
*/
@Modifying
@Query
(
"delete from RefreshToken rt where rt.tokenJti = ?1"
)
void
deleteByTokenJti
(
String
jti
);
/**
* Find by token jti.
*
* @param tokenJti the tokenJti
* @return the list
*/
RefreshToken
findByTokenJti
(
String
tokenJti
);
/**
* Delete expired tokens.
*
* @param date the date
*/
@Query
(
"delete from RefreshToken rt where rt.expiration < ?1"
)
@Modifying
int
deleteOlderThan
(
Date
date
);
}
src/main/java/org/gringlobal/service/JPATokenStore.java
0 → 100644
View file @
90723e9a
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org.gringlobal.service
;
import
java.util.List
;
import
org.gringlobal.model.jwt.AccessToken
;
import
org.gringlobal.model.jwt.RefreshToken
;
import
org.gringlobal.service.filter.OAuthAccessTokenFilter
;
import
org.gringlobal.service.filter.OAuthRefreshTokenFilter
;
import
org.springframework.data.domain.Page
;
import
org.springframework.data.domain.Pageable
;
import
org.springframework.security.oauth2.provider.token.TokenStore
;
/**
* @author Maxym Borodenko
*/
public
interface
JPATokenStore
extends
TokenStore
{
Page
<
AccessToken
>
listAccessTokens
(
OAuthAccessTokenFilter
filter
,
Pageable
page
);
Page
<
RefreshToken
>
listRefreshTokens
(
OAuthRefreshTokenFilter
filter
,
Pageable
page
);
AccessToken
getAccessTokenByJti
(
String
tokenJti
);