11/*******************************************************************************
22 * Copyright (C) 2024 the Eclipse BaSyx Authors
3- *
3+ *
44 * Permission is hereby granted, free of charge, to any person obtaining
55 * a copy of this software and associated documentation files (the
66 * "Software"), to deal in the Software without restriction, including
77 * without limitation the rights to use, copy, modify, merge, publish,
88 * distribute, sublicense, and/or sell copies of the Software, and to
99 * permit persons to whom the Software is furnished to do so, subject to
1010 * the following conditions:
11- *
11+ *
1212 * The above copyright notice and this permission notice shall be
1313 * included in all copies or substantial portions of the Software.
14- *
14+ *
1515 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1616 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1717 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
1818 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
1919 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
2020 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2121 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22- *
22+ *
2323 * SPDX-License-Identifier: MIT
2424 ******************************************************************************/
2525
3232import org .eclipse .digitaltwin .basyx .core .exceptions .AccessTokenRetrievalException ;
3333import org .slf4j .Logger ;
3434import org .slf4j .LoggerFactory ;
35+ import org .springframework .beans .factory .annotation .Value ;
3536
3637import com .nimbusds .oauth2 .sdk .AccessTokenResponse ;
3738import com .nimbusds .oauth2 .sdk .token .AccessToken ;
4243import com .nimbusds .jwt .JWTParser ;
4344import com .nimbusds .jwt .SignedJWT ;
4445
46+ import java .util .Collection ;
4547import java .util .Date ;
4648
4749/**
4850 * Requests and manages the Access Tokens and Refresh Tokens.
49- *
51+ *
5052 * @author danish
5153 */
5254import java .time .Instant ;
@@ -55,160 +57,20 @@ public class TokenManager {
5557
5658 private static final Logger LOGGER = LoggerFactory .getLogger (TokenManager .class );
5759
58- private static final String EXPIRES_IN = "expires_in" ;
59- private static final String REFRESH_EXPIRES_IN = "refresh_expires_in" ;
60- private final String tokenEndpoint ;
61- private final AccessTokenProvider accessTokenProvider ;
62- private String accessToken ;
63- private String refreshToken ;
64- private Instant accessTokenExpiryTime ;
65- private Instant refreshTokenExpiryTime ;
60+ @ Value ("${ld-sso.api-token}" )
61+ private String apiToken ;
6662
6763 public TokenManager (String tokenEndpoint , AccessTokenProvider accessTokenProvider ) {
68- this .tokenEndpoint = tokenEndpoint ;
69- this .accessTokenProvider = accessTokenProvider ;
70- }
71-
72- public String getTokenEndpoint () {
73- return tokenEndpoint ;
74- }
75-
76- public AccessTokenProvider getAccessTokenProvider () {
77- return this .accessTokenProvider ;
7864 }
7965
8066 /**
81- * Provides the access token, refreshing it if necessary .
82- *
67+ * Provides the access token.
68+ *
8369 * @return the current valid access token
8470 * @throws IOException
8571 * if an error occurs while retrieving the token
8672 */
8773 public String getAccessToken () throws IOException {
88- Instant currentTime = Instant .now ();
89-
90- if (accessToken != null && currentTime .isBefore (accessTokenExpiryTime ))
91- return accessToken ;
92-
93- synchronized (this ) {
94- if (accessToken != null && currentTime .isBefore (accessTokenExpiryTime ))
95- return accessToken ;
96-
97- if (refreshToken != null && currentTime .isBefore (refreshTokenExpiryTime ))
98- return refreshAccessToken (currentTime );
99-
100- return obtainNewAccessToken (currentTime );
101- }
102- }
103-
104- /**
105- * Updates the tokens and their expiry times.
106- *
107- * @param accessTokenResponse
108- * the response containing the new tokens
109- * @param currentTime
110- * the current timestamp for consistency
111- * @return the new access token
112- * @throws IOException
113- * if an error occurs while processing the response
114- */
115- private String updateTokens (AccessTokenResponse accessTokenResponse , Instant currentTime ) throws IOException {
116- AccessToken accessTokenObj = accessTokenResponse .getTokens ().getAccessToken ();
117- accessToken = accessTokenObj .getValue ();
118- accessTokenExpiryTime = calculateExpiryTime (accessTokenObj , currentTime );
119-
120- RefreshToken refreshTokenObj = accessTokenResponse .getTokens ().getRefreshToken ();
121-
122- if (refreshTokenObj != null ) {
123- refreshToken = refreshTokenObj .getValue ();
124- refreshTokenExpiryTime = calculateRefreshExpiryTime (refreshTokenObj , accessTokenResponse , currentTime );
125- }
126-
127- return accessToken ;
128- }
129-
130- /**
131- * Calculates the expiry time for a JWT token. First checks the 'exp' field in
132- * the JWT, falling back to 'expires_in'.
133- *
134- * @param tokenObj
135- * the AccessToken or RefreshToken object
136- * @param currentTime
137- * the current timestamp
138- * @return the calculated expiry time as Instant
139- */
140- private Instant calculateExpiryTime (AccessToken tokenObj , Instant currentTime ) {
141- String tokenValue = tokenObj .getValue ();
142- Date expirationDate = extractExpirationTimeAsDateFromToken (tokenValue );
143-
144- if (expirationDate != null )
145- return expirationDate .toInstant ();
146-
147- LOGGER .info ("Unable to find 'exp' claim inside Access Token! Falling back to the alternative, the '{}' field." , EXPIRES_IN );
148-
149- return currentTime .plusSeconds (tokenObj .getLifetime ());
150- }
151-
152- /**
153- * Calculates the expiry time for a refresh token. First checks the 'exp' field
154- * in the JWT refresh token, falling back to 'refresh_expires_in'.
155- *
156- * @param refreshTokenObj
157- * the RefreshToken object
158- * @param accessTokenResponse
159- * the response containing the refresh token
160- * @param currentTime
161- * the current timestamp
162- * @return the calculated expiry time as Instant
163- */
164- private Instant calculateRefreshExpiryTime (RefreshToken refreshTokenObj , AccessTokenResponse accessTokenResponse , Instant currentTime ) {
165- String tokenValue = refreshTokenObj .getValue ();
166- Date expirationDate = extractExpirationTimeAsDateFromToken (tokenValue );
167-
168- if (expirationDate != null )
169- return expirationDate .toInstant ();
170-
171- LOGGER .info ("Unable to find 'exp' claim inside Refresh Token! Falling back to the alternative, the '{}' field" , REFRESH_EXPIRES_IN );
172-
173- JSONObject jsonObject = accessTokenResponse .toJSONObject ();
174- Number refreshExpiresInSeconds = jsonObject .getAsNumber (REFRESH_EXPIRES_IN );
175-
176- if (refreshExpiresInSeconds == null )
177- return Instant .EPOCH ;
178-
179- return currentTime .plusSeconds (refreshExpiresInSeconds .longValue ());
180- }
181-
182- private Date extractExpirationTimeAsDateFromToken (String tokenValue ) {
183- try {
184- JWT jwt = JWTParser .parse (tokenValue );
185-
186- if (jwt instanceof SignedJWT ) {
187- SignedJWT signedJwt = (SignedJWT ) jwt ;
188- return signedJwt .getJWTClaimsSet ().getExpirationTime ();
189- }
190- } catch (ParseException e ) {
191- LOGGER .error ("Failed to parse the token. Invalid JWT format: " + e .getMessage ());
192- } catch (Exception e ) {
193- LOGGER .error ("Unexpected error occurred while extracting expiration time from the Token: " + e .getMessage ());
194- }
195-
196- return null ;
197- }
198-
199- private String obtainNewAccessToken (Instant currentTime ) {
200- try {
201- return updateTokens (accessTokenProvider .getAccessTokenResponse (tokenEndpoint ), currentTime );
202- } catch (IOException e ) {
203- throw new AccessTokenRetrievalException ("Error occurred while retrieving access token: " + e .getMessage ());
204- }
205- }
206-
207- private String refreshAccessToken (Instant currentTime ) {
208- try {
209- return updateTokens (accessTokenProvider .getAccessTokenResponse (tokenEndpoint , refreshToken ), currentTime );
210- } catch (IOException e ) {
211- throw new AccessTokenRetrievalException ("Error occurred while retrieving access token: " + e .getMessage ());
212- }
74+ return apiToken ;
21375 }
21476}
0 commit comments