-
Notifications
You must be signed in to change notification settings - Fork 1
(#154) Set Groups and Case Sensitivity to optional Parameters #155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,7 +21,7 @@ import org.slf4j.{Logger, LoggerFactory} | |
| import org.springframework.http.{HttpEntity, HttpHeaders, HttpMethod, MediaType, ResponseEntity} | ||
| import org.springframework.security.kerberos.client.KerberosRestTemplate | ||
| import org.springframework.web.client.RestTemplate | ||
| import za.co.absa.loginclient.tokenRetrieval.model.{AccessToken, RefreshToken} | ||
| import za.co.absa.loginclient.tokenRetrieval.model.{AccessToken, AuthMethod, BasicAuth, KerberosAuth, RefreshToken} | ||
|
|
||
| import java.net.URLEncoder | ||
| import java.util.{Collections, Properties} | ||
|
|
@@ -39,116 +39,50 @@ case class TokenRetrievalClient(host: String) { | |
| private val logger: Logger = LoggerFactory.getLogger(this.getClass) | ||
|
|
||
| /** | ||
| * This method requests an access token (JWT) from the login service using the specified username and password. | ||
| * This method requests an access token (JWT) from the login service using the specified authentication method. | ||
| * This Token is used to access resources which utilize the login Service for authentication. | ||
| * | ||
| * @param username The username used for authentication. | ||
| * @param password The password associated with the provided username. | ||
| * @param groups An optional list of PAM groups. If provided, only JWTs associated with these groups are returned if the user belongs to them. | ||
| * @param caseSensitiveGroups A boolean indicating whether the group prefixes should be treated as case sensitive. | ||
| * @param authMethod The authentication method to use. Either Basic Auth or Kerberos Auth. | ||
| * @param groups A list of group prefixes to include in the token. | ||
| * @param caseSensitiveGroups Whether the group prefixes are case sensitive. | ||
| * @return An AccessToken object representing the retrieved access token (JWT) from the login service. | ||
| */ | ||
| def fetchAccessToken( | ||
| username: String, | ||
| password: String, | ||
| groups: List[String], | ||
| caseSensitiveGroups: Boolean): AccessToken = { | ||
| fetchAccessAndRefreshToken(username, password, groups, caseSensitiveGroups)._1 | ||
| } | ||
|
|
||
| /** | ||
| * This method requests an access token (JWT) from the login service using SPNEGO. | ||
| * This Token is used to access resources which utilize the login Service for authentication. | ||
| * | ||
| * @param keytabLocation Optional location of the keytab file. | ||
| * @param userPrincipal Optional userPrincipal name included in the above keytab file. | ||
| * @param groups An optional list of PAM groups. If provided, only JWTs associated with these groups are returned if the user belongs to them. | ||
| * @param caseSensitiveGroups A boolean indicating whether the group prefixes should be treated as case sensitive. | ||
| * @return An AccessToken object representing the retrieved access token (JWT) from the login service. | ||
| */ | ||
| def fetchAccessToken( | ||
| keytabLocation: Option[String], | ||
| userPrincipal: Option[String], | ||
| groups: List[String], | ||
| caseSensitiveGroups: Boolean): AccessToken = { | ||
| fetchAccessAndRefreshToken(keytabLocation, userPrincipal, groups, caseSensitiveGroups)._1 | ||
| authMethod: AuthMethod, | ||
| groups: List[String] = List.empty, | ||
| caseSensitiveGroups: Boolean = false | ||
| ): AccessToken = { | ||
| fetchAccessAndRefreshToken(authMethod, groups, caseSensitiveGroups)._1 | ||
| } | ||
|
|
||
| /** | ||
| * This method requests a refresh token from the login service using SPNEGO. | ||
| * This token may be used to acquire a new access token (JWT) when the current access token expires. | ||
| * | ||
| * @param keytabLocation Optional location of the keytab file. | ||
| * @param userPrincipal Optional userPrincipal name included in the above keytab file. | ||
| * @param authMethod The authentication method to use. Either Basic Auth or Kerberos Auth. | ||
| * @return A RefreshToken object representing the retrieved refresh token from the login service. | ||
| */ | ||
| def fetchRefreshToken(keytabLocation: Option[String], userPrincipal: Option[String]): RefreshToken = { | ||
| fetchAccessAndRefreshToken(keytabLocation, userPrincipal, List.empty, false)._2 | ||
| } | ||
|
|
||
| /** | ||
| * This method requests a refresh token from the login service using the specified username and password. | ||
| * This token may be used to acquire a new access token (JWT) when the current access token expires. | ||
| * | ||
| * @param username The username used for authentication. | ||
| * @param password The password associated with the provided username. | ||
| * @return A RefreshToken object representing the retrieved refresh token from the login service. | ||
| */ | ||
| def fetchRefreshToken(username: String, password: String): RefreshToken = { | ||
| fetchAccessAndRefreshToken(username, password, List.empty, false)._2 | ||
| def fetchRefreshToken(authMethod: AuthMethod): RefreshToken = { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Neither the new method nor the existing (which should be present for some time as described above) seem to be covered with unit tests. That is unfortunate, because the appropriate class
|
||
| fetchAccessAndRefreshToken(authMethod)._2 | ||
| } | ||
|
|
||
| /** | ||
| * Fetches both an access token and a refresh token from the login service using the provided username, password, and optional groups. | ||
| * This method requests both an access token and a refresh token (JWTs) from the login service using the specified username and password. | ||
| * Additionally, it allows specifying optional groups that act as filters for the JWT, returning only the JWTs associated with the provided groups if the user belongs to them. | ||
| * | ||
| * @param username The username used for authentication. | ||
| * @param password The password associated with the provided username. | ||
| * @param groups An optional list of PAM groups. If provided, only JWTs associated with these groups are returned if the user belongs to them. | ||
| * @param caseSensitiveGroups A boolean indicating whether the group prefixes should be treated as case sensitive. | ||
| * @return A tuple containing the AccessToken and RefreshToken objects representing the retrieved access and refresh tokens (JWTs) from the login service. | ||
| * Additionally, it allows specifying optional groups (and their case sensitivity) that act as filters for the JWT, | ||
| * returning only the JWTs associated with the provided groups if the user belongs to them. | ||
| * @param authMethod The authentication method to use. | ||
| * @param groups A list of group prefixes to include in the token. | ||
| * @param caseSensitiveGroups Whether the group prefixes are case sensitive. | ||
| * @return A tuple containing the access token and the refresh token. | ||
| */ | ||
| def fetchAccessAndRefreshToken( | ||
| username: String, | ||
| password: String, | ||
| groups: List[String], | ||
| caseSensitiveGroups: Boolean | ||
| ): (AccessToken, RefreshToken) = { | ||
| val issuerUri = if(groups.nonEmpty) { | ||
| val commaSeparatedString = groups.mkString(",") | ||
| val urlEncodedGroups = URLEncoder.encode(commaSeparatedString, "UTF-8") | ||
| var uri = s"$host/token/generate?group-prefixes=$urlEncodedGroups" | ||
| if(caseSensitiveGroups) { | ||
| uri += "&case-sensitive=true" | ||
| } | ||
| uri | ||
| } else s"$host/token/generate" | ||
|
|
||
| val jsonString = fetchToken(issuerUri, username, password) | ||
| val jsonObject = JsonParser.parseString(jsonString).getAsJsonObject | ||
| val accessToken = jsonObject.get("token").getAsString | ||
| val refreshToken = jsonObject.get("refresh").getAsString | ||
| (AccessToken(accessToken), RefreshToken(refreshToken)) | ||
| } | ||
|
|
||
| /** | ||
| * Fetches both an access token and a refresh token from the login service using SPNEGO. | ||
| * This method requests both an access token and a refresh token (JWTs) from the login service using kerberos, either with a keytab or the users cached ticket. | ||
| * Additionally, it allows specifying optional groups that act as filters for the JWT, returning only the JWTs associated with the provided groups if the user belongs to them. | ||
| * | ||
| * @param keytabLocation Optional location of the keytab file. | ||
| * @param userPrincipal Optional userPrincipal name included in the above keytab file. | ||
| * @param groups An optional list of PAM groups. If provided, only JWTs associated with these groups are returned if the user belongs to them. | ||
| * @param caseSensitiveGroups A boolean indicating whether the group prefixes should be treated as case sensitive. | ||
| * @return A tuple containing the AccessToken and RefreshToken objects representing the retrieved access and refresh tokens (JWTs) from the login service. | ||
| */ | ||
| def fetchAccessAndRefreshToken( | ||
| keytabLocation: Option[String], | ||
| userPrincipal: Option[String], | ||
| groups: List[String], | ||
| caseSensitiveGroups: Boolean | ||
| authMethod: AuthMethod, | ||
| groups: List[String] = List.empty, | ||
| caseSensitiveGroups: Boolean = false | ||
| ): (AccessToken, RefreshToken) = { | ||
|
|
||
| val issuerUri = if(groups.nonEmpty) { | ||
| val commaSeparatedString = groups.mkString(",") | ||
| val urlEncodedGroups = URLEncoder.encode(commaSeparatedString, "UTF-8") | ||
|
|
@@ -159,13 +93,27 @@ case class TokenRetrievalClient(host: String) { | |
| uri | ||
| } else s"$host/token/generate" | ||
|
|
||
| val jsonString = fetchToken(issuerUri, keytabLocation, userPrincipal) | ||
| val jsonString = authMethod match { | ||
| case BasicAuth(username, password) => | ||
| fetchToken(issuerUri, username, password) | ||
| case KerberosAuth(keytabLocation, userPrincipal) => | ||
| fetchToken(issuerUri, keytabLocation, userPrincipal) | ||
| } | ||
|
|
||
| val jsonObject = JsonParser.parseString(jsonString).getAsJsonObject | ||
| val accessToken = jsonObject.get("token").getAsString | ||
| val refreshToken = jsonObject.get("refresh").getAsString | ||
| (AccessToken(accessToken), RefreshToken(refreshToken)) | ||
| } | ||
|
|
||
| /** | ||
| * Refreshes an access token using a refresh token. | ||
| * | ||
| * @param accessToken The access token to refresh. | ||
| * @param refreshToken The refresh token to use. | ||
| * @return A tuple containing the new access token and the existing refresh token. | ||
| */ | ||
|
|
||
| def refreshAccessToken(accessToken: AccessToken, refreshToken: RefreshToken): (AccessToken, RefreshToken) = { | ||
| val issuerUri = s"$host/token/refresh" | ||
|
|
||
|
|
@@ -204,6 +152,14 @@ case class TokenRetrievalClient(host: String) { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Sets the Kerberos properties for the JVM. | ||
| * | ||
| * @param jaasFileLocation The location of the JAAS file. | ||
| * @param krb5FileLocation The location of the krb5 file. | ||
| * @param debug Whether to enable Kerberos debugging. | ||
| */ | ||
|
|
||
| def setKerberosProperties(jaasFileLocation: String, krb5FileLocation: Option[String], debug: Option[Boolean]): Unit = { | ||
| val properties: Properties = new Properties() | ||
| properties.setProperty("java.security.auth.login.config", jaasFileLocation) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /* | ||
| * Copyright 2023 ABSA Group Limited | ||
| * | ||
| * 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 za.co.absa.loginclient.tokenRetrieval.model | ||
|
|
||
| sealed trait AuthMethod | ||
| case class BasicAuth(username: String, password: String) extends AuthMethod | ||
| case class KerberosAuth(keytabLocation: Option[String], userPrincipal: Option[String]) extends AuthMethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This being a library, we should not just remove API as if it was never there between versions.
The existing API should stay in place with
@deprecatedannotation (ideally internally calling the new methods and thus be ready for removal in the future).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, will do