{"id":18810327,"url":"https://github.com/absaoss/login-service","last_synced_at":"2026-02-05T13:18:16.964Z","repository":{"id":65782273,"uuid":"594057605","full_name":"AbsaOSS/login-service","owner":"AbsaOSS","description":"AbsaOSS Common Login gateway using JWT Public key signatures","archived":false,"fork":false,"pushed_at":"2024-10-21T13:07:58.000Z","size":247,"stargazers_count":2,"open_issues_count":14,"forks_count":0,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-10-21T20:07:32.298Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AbsaOSS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-27T13:58:20.000Z","updated_at":"2024-10-21T13:07:58.000Z","dependencies_parsed_at":null,"dependency_job_id":"902f3af3-f282-49b9-bdbd-e4c6b252c721","html_url":"https://github.com/AbsaOSS/login-service","commit_stats":null,"previous_names":["absaoss/login-service"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Flogin-service","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Flogin-service/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Flogin-service/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Flogin-service/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AbsaOSS","download_url":"https://codeload.github.com/AbsaOSS/login-service/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223603193,"owners_count":17172057,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T23:19:46.960Z","updated_at":"2026-02-05T13:18:16.952Z","avatar_url":"https://github.com/AbsaOSS.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# login-service\nAbsaOSS Common Login service using JWT Public key signatures\n\n## Basic use-case schematics\n![login-gw-basic-usecase2](https://user-images.githubusercontent.com/4457378/219037599-5674b63b-403c-4c02-8a54-a6e12dc01d47.png)\n\n### Usage \u0026 Integration\nTo interact with the service, most notable endpoints are\n - `/token/generate` to generate access \u0026 refresh tokens\n - `/token/refresh` to obtain a new access token with a still-valid refresh token\n - `/token/public-key` to obtain the currently signing public key to verify tokens including their validity window\n - `/token/public-keys` to obtain all available public keys including the current and previously rotated keys.\n - `/token/public-key-jwks` gives same data as `/token/public-keys` but in the form of a JSON Web Key Set.\n\nPlease, refer to the [API documentation](#api-documentation) below for details of the endpoints.\n\n#### Generate tokens\nOnce you request your token at `/token/generate` endpoint, you will receive both an access token and a refresh token\n```json\n{\n  \"token\": \"...\",\n  \"refresh\": \"...\"\n}\n```\nBoth tokens are signed by LS public key and carry the username (`sub`), `type` (`access`/`refresh`) and creation/expiry info (`iat`/`exp`). \n\n#### Refresh access token\nDuring the time the refresh token is valid, you may refresh the access token (expired or not) using the `/token/refresh` \nendpoint - as the service does not facilitate any internal service access to LDAP, both tokens must be sent. \n\n#### Validate access token\nOn the side of the integrator, in order to trust the access token, one should do the following actions:\n1. obtain the public-key from LS at `/token/public-key`\n2. verify that the access token\n   1. is valid against this public-key (e.g. using `jwtt` library or similar)\n   2. is not expired\n   3. has `type=access`\n\n## API documentation:\nSwagger doc site is available at `http://localhost:port/swagger-ui.html`\n(substitute `http://localhost:port` with any possible host and port you have deployed your package to.)\n### Need the OpenAPI 3 yaml file?\nIt is available for download while running the service at `http://localhost:port/v3/api-docs.yaml` -\ngets generated from code (specifically from Spring annotations)\n\n\n## Configuration\nThe project requires a valid configuration file to run.\nAn [example configuration](https://github.com/AbsaOSS/login-service/blob/master/service/src/main/resources/example.application.yaml)\nfile is provided to take inspiration from.\n\nThe project will look for the Spring config in multiple places and\nin a specific order precisely as described at \n[Spring boot - Externalized Configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config).\nWithout having to study the whole documentation section, let us offer a few simple ways:\n\n### Locally available `application.yaml`\nIf you are looking to build and run locally, just supply the following argument:\n```\n--spring.config.location=api/src/main/resources/example.application.yaml\n```\nor set the following Environment Variable:\n```\n\"SPRING_CONFIG_LOCATION=api/src/main/resources/example.application.yaml\"\n```\nand you will be up and running.\nThis will run the application using the provided example config for usage in local tests/development.\n\n### Supply argument `--spring.config.location=my/path/my.application.yaml`\nExternally-defined-`application.yaml` option that will not package (i.e. pollute) the resulting package.\n\nShown in IDEA:\n\n![spring-config-location-idea-example-censored](https://github.com/AbsaOSS/login-service/assets/4457378/02390dbe-0b71-48e3-a3ea-b6ca7f6ea500)\n  \n\n## Source idea\nThe implementation is heavily inspired by [Enceladus](https://github.com/AbsaOSS/enceladus) that already contained \na similar single purpose login functionality with JWT. Also, Tomcat@SBT implementation is on the other hand drawn from \n[atum-service](https://github.com/AbsaOSS/atum-service).\n\n\n## Current development state\nCurrently, only a skeleton of the project exists. The project uses `xsbt-web-plugin` plugin, therefore to get\nthe service running (also builds the service `war`), one can run:\n\n```\nsbt\nservice / Tomcat / start\n```\n\n## Authentication Providers\n### Enabling and Selecting Authentication Providers\nThe Login Service allows users to select which authentication providers they would like to use\nas well as the order in which the authentication methods get prioritized.\n\nThis is done by setting a number (Greater than 0) on the `order` tag for each auth method.\nthe number used indicates the order in which you would like to use the method.\n\nFor Example:\nThe 2 methods currently enabled are config specified users:\n```\nloginsvc.rest.auth.provider.users.order = 1\n```\nand LDAP:\n```\nloginsvc.rest.auth.provider.ldap.order = 2\n```\nIn the above example, both methods are enabled with the config specified users taking priority over Ldap.\n\nIn order to disable an authentication protocol, set the `order` property to `0`\nor just exclude the properties from the config for that auth provider.\nPlease ensure at least one auth method is enabled.\n\nFor the service account used to search LDAP, the Service Account Name and password may be specified in the config file.\nFor a more secure approach, the service account name and password may be specified in AWS Secrets Manager\nor in AWS Systems Manager Parameter Store and the application will fetch them from there.\n\nThe config also allows the user to specify additional claims to be added to the JWT token. \nThese can be sourced from LDAP or specified directly in the config depending on the auth provider used.\n\nFormat of attributes list under LDAP in config is:\n```\n        ldap:\n          # Auth Protocol\n          # Set the order of the protocol starting from 1\n          # Set to 0 to disable or simply exclude the LDAP tag from config\n          # NOTE: At least 1 auth protocol needs to be enabled\n          order: 2\n          domain: \"some.domain.com\"\n          url: \"ldaps://some.domain.com:636/\"\n          search-filter: \"(samaccountname={1})\"\n          service-account:\n            account-pattern: \"CN=%s,OU=Users,OU=CORP Accounts,DC=corp,DC=dsarena,DC=com\"\n            in-config-account:\n                username: \"svc-ldap\"\n                password: \"password\"\n          attributes:\n            \u003cldapFieldName\u003e: \"\u003cclaimName\u003e\"\n```\n\n`ldapFieldName` is the name of the field in the LDAP server and `claimName` is the name of the claim that will be added to the JWT token.\n\nIn order to utilize AWS services in order to store your service account details, replace `in-config-account` with:\n```\n            aws-secrets-manager-account:\n              secret-name: \"secret\"\n              region: \"region\"\n              username-field-name: \"username\"\n              password-field-name: \"password\"\n```\nThis will retrieve these details securely from AWS secrets manager.\nAlternatively:\n```\n            aws-systems-manager-account:\n              parameter: \"/parameter/path\"\n              decrypt-if-secure: true\n              username-field-name: \"username\"\n              password-field-name: \"password\"\n```\nThis will retrieve these details securely from AWS systems manager parameter store.\n\n### Enabling SPNEGO authentication with LDAP\nWhen LDAP authentication is used, there is the option of adding SPNEGO authentication via kerberos.\nThis will allow users to authenticate via Basic Auth or Kerberos Tickets.\nThe Config to enable this will look like this:\n```\n        ldap:\n          enable-kerberos:\n            krb-file-location: \"/etc/krb5.conf\"\n            keytab-file-location: \"/etc/keytab\"\n            spn: \"HTTP/Host\"\n            debug: true\n```\nAdding the `enable-kerberos` property to the config will enable SPNEGO authentication.\nIn order to facilitate the kerberos authentication, you will need to provide a krb5 file that includes \nthe kerberos configuration details such as domains and Kerberos distribution center address.\nA Keytab file needs to be created and attached to the service. The SPN needs to match that which\nis used in the keytab and matches the host of the Login Service. The `debug` property is used when\nadditional information is required from the logs when testing the service.\n\n### Enable LDAP authentication retries\nWhen LDAP authentication is used, there is the option to enable LDAP service retries.\nThis allows the service to retry and repeat calls to the LDAP service when the service is unreachable.\nThis protects the user from authentication errors when there are brief interruptions in the Ldap service or on the network.\nThe Config to enable this will look like this:\n```\n        ldap:\n          ldap-retry:\n            attempts: 3\n            delay-ms: 100\n```\nAdding the `ldap-retry` property to the config will enable LDAP retry functionality.\nThe `attempts` property dictates the amount of retry attempts will occur before an exception is communicated to the user.\nThe `delay-ms` indicates the base timing between each delay. The delay for each retry is multiplied by the current attempt.\nIn the above example configuration, the process for failure will work as follows:\n1. Initial communication to LDAP occurs and fails\n2. 100ms delay\n3. 1st retry attempt occurs and fails\n4. 200ms delay\n5. 2nd retry attempt occurs and fails\n6. 300ms delay\n7. 3rd retry attempt occurs and fails\n8. Authentication fails and exception is communicated to user.\n\n### ActiveDirectoryLDAPAuthenticationProvider\nUses LDAP(s) to authenticate user in Active Directory and to fetch groups that this user belongs to.\n\nRequires `ActiveDirectoryLDAPConfig(domain: String, url: String, searchFilter: String)`.\n#### Tips\n##### How to obtain certificate for LDAPS\n1. Run `openssl s_client -connect \u003cldaps_host\u003e:\u003cldaps_port\u003e`.\n2. Copy the part starting with `-----BEGIN CERTIFICATE-----` and ending with `-----END CERTIFICATE-----`. \n3. Create file `ldapcert.pem` and paste content from (2) there.\n4. Import the certificate to `cacarts`:\n   - For JDK8: Run `keytool -import -file ldapcert.pem -alias ldaps -keystore \u003cpath_to_jdk\u003e/jre/lib/security/cacerts -storepass \u003cpassword\u003e` (default password is *changeit*).\n   - For JDK11: Run `keytool -import -file ldapcert.pem -alias ldaps -keystore \u003cpath_to_jdk\u003e/lib/security/cacerts -storepass \u003cpassword\u003e` (default password is *changeit*).\n5. Enter `yes` when prompted.\n\n## Key Provider\nThe Application allows for the user to allow the application to generate a key in memory.\nThis is useful for single deployments and testing, however, may present issues when trying to deploy multiple login-services for redundancy.\nTo get around this, the application allows for you to generate your keys in AWS Secrets manager and the application will periodically fetch them.\n\nIn order to setup for in-memory key generation, your config should look like so:\n```\nloginsvc:\n  rest:\n    jwt:\n      generate-in-memory:\n         access-exp-time: 15min\n         refresh-exp-time: 9h\n         key-rotation-time: 9h\n         key-lay-over-time: 15min\n         key-phase-out-time: 30min\n         alg-name: \"RS256\"\n```\nThere are a few important configuration values to be provided:\n- `access-exp-time` which indicates how long an access token is valid for,\n- `refresh-exp-time` which indicates how long a refresh token is valid for,\n- Optional property: `key-rotation-time` which indicates how often Key pairs are rotated. Rotation will be disabled if missing.\n- Optional property: `key-lay-over-time` which indicates a delay after rotation before using the newly created key for signing. Lay-over will be disabled if missing.\n- Optional property: `key-phase-out-time` which indicates the time to phase out the older key. Timer is scheduled after `key-lay-over-time` if enabled. Phase-out will be disabled if missing.\n- `alg-name` which indicates which algorithm is used to encode your keys.\n\nUsing the above values, the optional properties will give the following effect after the 1st rotation at 9 hours:\n```\nt=0: keys rotation happens\nt=0-14m: layover period: old key from before rotation is still used for signing. Both public keys available from public-keys endpoint.\nt=15-44m: layover is over: new key from after rotation is used for signing. Both public keys available from public-keys endpoint.\nt=45m+: phase-out happens: new key from after rotation is used for signing. Old Key is no longer available from public-keys endpoint.\n```\nThese properties cannot be enabled if rotation is not enabled. The combined values of these properties cannot be higher than the rotation time.\n\n\nTo setup for AWS Secrets Manager, your config should look like so:\n```\nloginsvc:\n  rest:\n    jwt:\n      aws-secrets-manager:\n        secret-name: \"secret\"\n        region: \"region\"\n        private-key-field-name: \"privateKey\"\n        public-key-field-name: \"publicKey\"\n        access-exp-time: 15min\n        refresh-exp-time: 9h\n        poll-time: 30min\n        key-lay-over-time: 15min\n        key-phase-out-time: 30min\n        alg-name: \"RS256\"\n```\nYour AWS Secret must have at least 2 fields which correspond to the above properties:\n```\nprivate-key-field-name: \"privateKey\"\npublic-key-field-name: \"publicKey\"\n```\nwith `\"privateKey\"` and `\"publicKey\"` indicating the field-name of those secrets.\nReplace the above example values with the field-names you used in AWS Secrets Manager.\n\nThere are a few important configuration values to be provided:\n- `access-exp-time` which indicates how long an access token is valid for,\n- `refresh-exp-time` which indicates how long a refresh token is valid for,\n- Optional property:`poll-time` which indicates how often key pairs (`private-key-field-name` and `public-key-field-name`) are polled and fetched from AWS Secrets Manager. Polling will be disabled if missing.\n- Optional property: `key-lay-over-time` which indicates a delay after rotation before using the newly created key for signing. Lay-over will be disabled if missing.\n- Optional property: `key-phase-out-time` which indicates the time to phase out the older key. Timer is scheduled after `key-lay-over-time` if enabled. Phase-out will be disabled if missing.\n- `alg-name` which indicates which algorithm is used to encode your keys.\n  Using the above values, the optional properties will give the following effect after the 1st rotation at 9 hours:\n```\nt=0: keys rotation happens\nt=0-14m: layover period: old key from before rotation is still used for signing. Both public keys available from public-keys endpoint.\nt=15-44m: layover is over: new key from after rotation is used for signing. Both public keys available from public-keys endpoint.\nt=45m+: phase-out happens: new key from after rotation is used for signing. Old Key is no longer available from public-keys endpoint.\n```\nThese properties cannot be enabled if polling is not enabled.\n  \nPlease note that only one configuration option (`loginsvc.rest.jwt.{aws-secrets-manager|generate-in-memory}`) can be used at a time.\n\n## Generating Tokens via SPNEGO/Kerberos\nTo securely authenticate and retrieve a JWT token from a server using Kerberos and SPNEGO, clients (both Windows and Linux) need to be properly configured for Kerberos authentication. \nThe process involves obtaining a Kerberos ticket and using it to authenticate to the endpoint.\n\n### Steps for Windows Clients\n#### 1) Kerberos Configuration:\n\n- Ensure the Windows client is joined to the appropriate Active Directory (AD) domain.\n- Verify that the Kerberos configuration is correct in the `krb5.ini` file, typically located in `C:\\ProgramData\\MIT\\Kerberos5\\` or `C:\\Windows\\`.\nThe `krb5.ini` file should include the correct realm and KDC settings. An example configuration might look like this:\n```\n[libdefaults]\n    default_realm = YOURDOMAIN.COM\n    dns_lookup_realm = false\n    dns_lookup_kdc = true\n\n[realms]\n    YOURDOMAIN.COM = {\n        kdc = kdc.yourdomain.com\n        admin_server = kdc.yourdomain.com\n    }\n\n[domain_realm]\n    .yourdomain.com = YOURDOMAIN.COM\n    yourdomain.com = YOURDOMAIN.COM\n```\n#### 2) Optional: MIT Kerberos Installation:\n\n- While Windows has built-in Kerberos support, you may choose to install MIT Kerberos if you need advanced features or compatibility with specific applications.\n- Download the installer from the [MIT Kerberos website](https://web.mit.edu/kerberos/dist/).\n- Follow the installation instructions, and ensure the krb5.ini file is properly configured as mentioned above.\n\n#### 3) Check Kerberos Tickets:\n\n- Use the `klist` command in the Command Prompt or use MIT Kerberos to verify the presence of a valid Kerberos ticket.\n```\nCredentials cache: API:1000\n        Principal: user@EXAMPLE.COM\n    Cache version: 5\n  Ticket cache: /tmp/krb5cc_1000\n  Default principal: user@EXAMPLE.COM\n\nValid starting       Expires              Service principal\n10/20/2024 10:00:00 10/20/2024 20:00:00 krbtgt/EXAMPLE.COM@EXAMPLE.COM\n10/20/2024 10:00:00 10/20/2024 20:00:00 host/server.example.com@EXAMPLE.COM\n```\n\n#### 4) Environment Setup:\n\n- Ensure that the required libraries (e.g., SPNEGO) are available in your application or tool (e.g., Postman, Curl).\n\n#### 5) Sending the POST Request:\n\n- Construct a POST request to the desired endpoint.\n- Example using Curl:\n```\ncurl -i --negotiate -u : -X POST \u003cendpoint-url\u003e/token/generate\n```\n\n#### 6) Receive the JWT:\n\n- On successful authentication, the server will respond with an access and refresh JWT tokens.\n\n### Steps for Linux Clients\n#### 1) Kerberos Installation:\n\n- Install the necessary Kerberos packages (e.g., krb5-libs).\n\n#### 2) Kerberos Configuration:\n\n- Locate and, if necessary, replace krb5.conf. The krb5.conf file is typically located in /etc/krb5.conf.\n- Ensure it includes the correct realm and KDC (Key Distribution Center) settings. A basic configuration might look like this:\n```\n[libdefaults]\n    default_realm = YOURDOMAIN.COM\n    dns_lookup_realm = false\n    dns_lookup_kdc = true\n\n[realms]\n    YOURDOMAIN.COM = {\n        kdc = kdc.yourdomain.com\n        admin_server = kdc.yourdomain.com\n    }\n\n[domain_realm]\n    .yourdomain.com = YOURDOMAIN.COM\n    yourdomain.com = YOURDOMAIN.COM\n```\n\n#### 3) Obtaining a Kerberos Ticket:\n\n- Use the following command to obtain a Kerberos ticket (A password may be required):\n```\nkinit username@YOURDOMAIN.COM\n```\n\n#### 4) Sending the POST Request:\n\n- Use a tool like Curl to send a POST request:\n```\ncurl -i --negotiate -u : -X POST \u003cendpoint-url\u003e/token/generate\n```\n\n#### 5) Receive the JWT:\n\n- On successful authentication, the server will respond with an access and refresh JWT tokens.\n\n## How to generate Code coverage report\n```\nsbt jacoco\n```\nCode coverage will be generated on path:\n```\n{project-root}/{module}/target/jacoco/report/index.html\n```\n## Health check endpoint\nSpringboot Actuator is enabled for this project. This provides the user with an endpoint (readable via HTTP or JMX)\nthat describes the overall status of the login-service as well as its parts.\n### Accessing health endpoint via http\nHealth Endpoint can be accessed via http using the following URL: `http://localhost:port/actuator/health`\nAccessing the above should give you the following Json message if all is functional and healthy:\n```\n    {\"status\":\"UP\"}\n```\nIf one of the monitored dependencies are unavailable or unhealthy then you will get:\n```\n    {\"status\":\"DOWN\"}\n```\nIf you wish for a full breakdown of the applications health including all dependencies then add the following to the application.properties file:\n```\n    management.endpoint.health.show-details=always\n```\nThe health endpoint is also available via the Swagger: `http://localhost:port/swagger-ui.html`\n### Using JMX to monitor /actuator/health\nLocal JMX is currently enabled on the project. In order to utilize it please follow the following steps:\n#### Steps\n1. Start the login-service application.\n2. Open a terminal or command prompt and run the following command to start JConsole:\n    ```\n    jconsole\n    ```\n3. In the JConsole window that opens, select the process corresponding to the login-service application from the list of local processes.\n4. Click the Connect button. JConsole will connect to the JMX agent running in the login-service application.\n5. In the MBean tab, expand the org.springframework.boot domain to see the available JMX endpoints.\n6. Find the health endpoint and click on it to view its attributes and operations. You can use the attributes and operations to check the health of the login-service and perform management tasks.\nYou can now use JConsole to monitor and manage your local application by accessing the available endpoints.\nRemote JMX is also an option and may be enabled with some config changes in the application.properties file.\n\n## Info endpoint\nSpringboot Actuator is enabled for this project. This enables an Info endpoint that can be populated with various information that may be\nuseful to the troubleshooting and usage of the application. The endpoint can be accessed via the following url:  `http://localhost:port/actuator/info`.\nThe information types available and how to use them is shown in the example config (`example.application.yaml`).\n\nRunning the example config will get you the following output:\n\n ```\n{\"app\":{\"name\":\"login-service\",\"build\":\"0.1\",\"description\":\"Application used a reusable authentication tool\",\"env\":\"Dev\"},\"security\":{\"ldap\":\"Enabled\"},\"git\":{\"commit\":{\"id\":{\"full\":\"git_id\"},\"message\":{\"full\":\"Added Git Properties\"},\"user\":{\"email\":\"exampleuser@org.com\"},\"time\":\"5/15/2023\"}}}\n ```\n\nIf you wish to change what is shown here, you can do so by changing the fields and attributes in the application file. \nMore info on the Actuator Info Service can be found here: https://reflectoring.io/spring-boot-info-endpoint/\n\n## git.properties\nAn example git.properties file has also been included (`example.git.properties`), simply rename it to `git.properties` in order to make use of it in the info endpoint.\nIf you wish to generate an accurate `git.properties file`, you can do so in 2 ways:\n\n1) Setting the `loginsvc.rest.config.git-info.generate-git-properties` to `true` will display newly generated git information.\n   Additionally setting `loginsvc.rest.config.git-info.generate-git-properties-file` to `true` will generate a new file with the updated git information on application startup.\n2) By manually adjusting and running the test in `za.co.absa.logingw.rest.actuator.tooling.GitPropertiesGenerator.scala`\n   In order to run the test the line (line 30) that reads as:\n   ```\n   ignore should \"generate git.properties file\" in {\n   ```\n   should be changed to:\n   ```\n   \"This function\" should \"generate git.properties file\" in {\n   ```\n   once this is done, running or debugging the test will generate a `git.properties` file to be used for the info endpoint.\n\nThis requires Git to be installed and available on the host.\nThe example `git.properties` file provided may be edited manually if the git generation is functioning incorrectly.\n\n## Client Library\nSee Readme in [clientLibrary](clientLibrary/README.md) module.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsaoss%2Flogin-service","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabsaoss%2Flogin-service","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsaoss%2Flogin-service/lists"}