{"id":18048077,"url":"https://github.com/ivangfr/okta-springboot","last_synced_at":"2025-04-10T09:48:36.168Z","repository":{"id":111328495,"uuid":"237630009","full_name":"ivangfr/okta-springboot","owner":"ivangfr","description":"The goal of this project is to develop a straightforward Spring Boot REST API application, named simple-service, which utilizes Okta for authentication handling.","archived":false,"fork":false,"pushed_at":"2025-01-03T19:24:51.000Z","size":2986,"stargazers_count":7,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T08:42:34.547Z","etag":null,"topics":["java","jib","oauth2-client","oauth2-resource-server","okta","spring-boot","spring-security","spring-web-mvc","thymeleaf"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivangfr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"ivangfr"}},"created_at":"2020-02-01T14:53:51.000Z","updated_at":"2025-01-09T13:30:40.000Z","dependencies_parsed_at":"2024-10-30T20:21:29.899Z","dependency_job_id":null,"html_url":"https://github.com/ivangfr/okta-springboot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fokta-springboot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fokta-springboot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fokta-springboot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fokta-springboot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivangfr","download_url":"https://codeload.github.com/ivangfr/okta-springboot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248197426,"owners_count":21063619,"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":["java","jib","oauth2-client","oauth2-resource-server","okta","spring-boot","spring-security","spring-web-mvc","thymeleaf"],"created_at":"2024-10-30T20:11:19.779Z","updated_at":"2025-04-10T09:48:36.149Z","avatar_url":"https://github.com/ivangfr.png","language":"Java","funding_links":["https://github.com/sponsors/ivangfr"],"categories":[],"sub_categories":[],"readme":"# okta-springboot\n\nThe objective of this project is to develop a secure `simple-service` application using [Spring Boot](https://docs.spring.io/spring-boot/index.html) and integrate it with [`Okta`](https://www.okta.com/) for authentication and authorization.\n\n\u003e **Note**: In the repository [`okta-springboot-react`](https://github.com/ivangfr/okta-springboot-react) you can find a more complex example that involves:\n\u003e - Implementation of a [`ReactJS`](https://reactjs.org/) front-end application and a `Spring Boot` back-end application, both secured by `Okta`;\n\u003e - Enabling and creating `Okta` groups (a.k.a. `ROLES` of the applications).\n\n## Proof-of-Concepts \u0026 Articles\n\nOn [ivangfr.github.io](https://ivangfr.github.io), I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.\n\n## Additional Readings\n\n- \\[**Medium**\\] [**Implementing and Securing a Simple Spring Boot REST API with Okta**](https://medium.com/@ivangfr/implementing-and-securing-a-simple-spring-boot-rest-api-with-okta-a5143696cd60)\n- \\[**Medium**\\] [**Implementing and Securing a Simple Spring Boot UI (Thymeleaf + RBAC) with Okta**](https://medium.com/@ivangfr/implementing-and-securing-a-simple-spring-boot-ui-thymeleaf-rbac-with-okta-9489cbbcec25)\n- \\[**Medium**\\] [**Implementing and Securing a Spring Boot GraphQL API with Okta**](https://medium.com/@ivangfr/implementing-and-securing-a-spring-boot-graphql-api-with-okta-78bc997359b4)\n- \\[**Medium**\\] [**Building a Single Spring Boot App with Keycloak or Okta as IdP: Introduction**](https://medium.com/@ivangfr/building-a-single-spring-boot-app-with-keycloak-or-okta-as-idp-introduction-2814a4829aed)\n\n## Project Diagram\n\n![project-diagram](documentation/project-diagram.jpeg)\n\n## Application\n\n- ### simple-service\n\n  `Spring Boot` Web Java application offers a user interface (UI) that requires users to log in using their `Okta` accounts. After successful login, users can access and view both their public and private messages.\n\n  | Login                                    | Index                                    |\n  |------------------------------------------|------------------------------------------|\n  | ![ui-login](documentation/ui-login.jpeg) | ![ui-index](documentation/ui-index.jpeg) |\n\n  It also exposes the following endpoints:\n\n  | Endpoint                   | Description                                                                                         | Secured |\n  |----------------------------|-----------------------------------------------------------------------------------------------------|---------|\n  | `GET /api/private`         | Retrieve the private message. Only accessible by users that provide a Access Token issued by `Okta` | YES     |\n  | `GET /api/public`          | Retrieve the public message                                                                         | NO      |\n  | `POST /api/callback/token` | Used by `Okta` to return user's Access Token                                                        | NO      |\n\n## Prerequisites\n\n- [`Java 21`](https://www.oracle.com/java/technologies/downloads/#java21) or higher;\n- [`Okta` account](https://developer.okta.com/signup/)\n- A containerization tool (e.g., [`Docker`](https://www.docker.com), [`Podman`](https://podman.io), etc.)\n\n## Configure Okta\n\n### Access Developer Edition Account\n\n- If you do not have a Developer Edition Account, you can create one at https://developer.okta.com/signup/\n- If you already have, access https://developer.okta.com/login/\n\n### Access Okta Admin Dashboard\n\nIf you are in `Okta Developer Dashboard` home page, click `Admin` button on the top-right\n\n![okta-developer-home](documentation/okta-developer-home.jpeg)\n\nThe picture below is how `Okta Admin Dashboard` looks like\n\n![okta-admin-dashboard](documentation/okta-admin-dashboard.jpeg)\n\n### Add Application\n\n- In the `Okta Admin Dashboard` main menu on the left, click `Applications` menu and then `Applications` sub-menu\n- In the next page, click `Create App Integration` button\n- Select `OIDC - OpenID Connect` as _Sign on method_ and `Web Application` as _Application type_. Click `Next` button\n- Enter the following values in the form\n  - General Settings\n    - App integration name: `Simple Service`\n    - Grant type: besides `Authorization Code` that is already checked, check also `Implicit (hybrid)`\n    - Sign-in redirect URIs: `http://localhost:8080/login/oauth2/code/okta` and `http://localhost:8080/api/callback/token`\n    - Sign-out redirect URIs: `http://localhost:8080`\n  - Assignments\n    - Controlled access: `Skip group assignment for now`\n- Click `Save` button\n- The `Client ID` and `Client Secret` are generated.\n- The `Okta Domain` can be obtained by clicking the button-menu present on the up-right corner of the screen.\n  \n### Add Person\n\n- In the `Okta Admin Dashboard` main menu on the left, click `Directory` menu and then `People` sub-menu\n- In the next page, click `Add person` button\n- Enter the following information\n  - First name: `Mario`\n  - Last name: `Bros`\n  - Username: `mario.bros@test.com`\n  - Primary email: `mario.bros@test.com`\n  - Password: `Set by admin`\n  - Set a strong password in the text-field that will appear\n  - `Uncheck` the check-box that says _\"User must change password on first login\"_\n- Click `Save` button\n\n### Assign Person to Application\n\n- In the `Okta Admin Dashboard` main menu on the left, click `Applications` menu and then `Applications` sub-menu\n- In the next page, click `Assign Users to App` button\n- Select the `Simple Service` check-box in the _Applications_ column and `Mario Bros` check-box in the _People_ column. Click `Next` button to continue assignment process\n- Click `Confirm Assignments` button\n\n### Fix Person username\n\n\u003e **Warning**: if we don't do the fix, we will see the following error\n\u003e ```\n\u003e {\"state\":\"state\",\"error\":\"server_error\",\"error_description\":\"The 'sub' system claim could not be evaluated.\"}\n\u003e```\n- In the `Okta Admin Dashboard` main menu on the left, click `Applications` menu and then `Applications` sub-menu\n- In Applications list whose status are `ACTIVE`, select `Simple Service` application\n- Click `Assignments` tab\n- Edit `Mario Bros` by clicking the `pen` icon\n- Set `mario.bros@test.com` in the `Username` text-field\n- Click `Save` button\n\n## Start application\n\n- Open a terminal and make sure you are in `okta-springboot` root folder\n\n- Export the following environment variables. Those values were obtained while [adding application](#add-application) in `Okta`.\n  ```\n  export OKTA_DOMAIN=...\n  export OKTA_CLIENT_ID=...\n  export OKTA_CLIENT_SECRET=...\n  ```\n\n- ### Running application using Maven\n\n  ```\n  ./mvnw clean spring-boot:run --projects simple-service\n  ```\n\n- ### Running application as a Docker container\n\n  - **Build Docker Image**\n    ```\n    ./build-docker-images.sh\n    ```\n\n   **Environment Variables**\n    \n    | Environment Variable | Description                                 |\n    |----------------------|---------------------------------------------|\n    | `OKTA_DOMAIN`        | Specify the `Domain` defined by Okta        |\n    | `OKTA_CLIENT_ID`     | Specify the `Client ID` defined by Okta     |\n    | `OKTA_CLIENT_SECRET` | Specify the `Client Secret` defined by Okta |\n\n  - **Start Docker Container**\n    \n    ```\n    docker run --rm --name simple-service -p 8080:8080 \\\n    -e OKTA_DOMAIN=${OKTA_DOMAIN} \\\n    -e OKTA_CLIENT_ID=${OKTA_CLIENT_ID} \\\n    -e OKTA_CLIENT_SECRET=${OKTA_CLIENT_SECRET} \\\n    ivanfranchin/simple-service:1.0.0\n    ```\n## Application URLs\n\n| Application    | Type    | URL                                   |\n|----------------|---------|---------------------------------------|\n| simple-service | UI      | http://localhost:8080                 |\n| simple-service | Swagger | http://localhost:8080/swagger-ui.html |\n\n## Getting Access Token\n\nIn order to access the `simple-service` secured endpoints, you must have a Access Token. Below are the steps to get it.\n\n- In a terminal, create the following environment variables. Those values were obtained while [adding application](#add-application) in `Okta`.\n  ```\n  OKTA_DOMAIN=...\n  OKTA_CLIENT_ID=...\n  ```\n\n- Get Okta Access Token Url\n  ```\n  OKTA_ACCESS_TOKEN_URL=\"https://${OKTA_DOMAIN}/oauth2/default/v1/authorize?\\\n  client_id=${OKTA_CLIENT_ID}\\\n  \u0026redirect_uri=http://localhost:8080/api/callback/token\\\n  \u0026scope=openid\\\n  \u0026response_type=token\\\n  \u0026response_mode=form_post\\\n  \u0026state=state\\\n  \u0026nonce=myNonceValue\"\n\n  echo $OKTA_ACCESS_TOKEN_URL\n  ```\n\n- Copy the Okta Access Token Url from the previous step and paste it in a browser\n\n- The Okta login page will appear. Enter the username \u0026 password of the person added at the step [`Configuring Okta \u003e Add person`](#add-person) and click `Sign In` button\n\n- It will redirect to `api/callback/token` endpoint of `simple-service` and the `Access token` will be displayed, together with other information\n  ```\n  {\n    \"state\": \"state\",\n    \"access_token\": \"eyJraWQiOiJyNFdY...\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": \"3600\",\n    \"scope\": \"openid\"\n  }\n  ```\n  \u003e **Note**: In [jwt.io](https://jwt.io), you can decode and verify the Access Token\n\n## Calling simple-service endpoints using curl\n\n- **`GET api/public`**\n\n  The `api/public` endpoint is not secured, so we can call it without any problem.\n  ```\n  curl -i http://localhost:8080/api/public\n  ```\n  It should return\n  ```\n  HTTP/1.1 200\n  It's a public message.\n  ```\n\n- **`GET api/private` without Access Token**\n\n  Try to call `api/private` endpoint without informing the Access Token.\n  ```\n  curl -i http://localhost:8080/api/private\n  ```\n  It should return\n  ```\n  HTTP/1.1 401\n  ```\n\n- **`GET api/private` with Access Token**\n\n  First, get the access token as explained in [`Getting Access Token`](#getting-access-token) section. Then, create an environment variable for the access token\n  ```\n  ACCESS_TOKEN=...\n  ```\n\n  Call `api/private` endpoint informing the access token.\n  ```\n  curl -i http://localhost:8080/api/private -H \"Authorization: Bearer $ACCESS_TOKEN\"\n  ```\n  Response\n  ```\n  HTTP/1.1 200\n  mario.bros@test.com, it's a private message.\n  ```\n\n## Using simple-service Swagger\n\n- Access http://localhost:8080/swagger-ui.html\n- Get the access token as explained in [`Getting Access Token`](#getting-access-token) section.\n- Click `Authorize` button. Paste the Access Token in the `Value` field. Then, click `Authorize` and `Close` to finalize.\n- Done! You can now access the sensitive endpoints.\n\n## Shutdown\n\nGo to the terminal where the application is running and press `Ctrl+C`\n\n## Running Test Cases\n\nIn a terminal and inside `okta-springboot` root folder, run the command below\n```\n./mvnw clean test --projects simple-service\n```\n\n## Cleanup\n\n### Docker image\n\nTo remove the Docker images created by this project, go to terminal and, inside `okta-springboot` root folder, run the following script\n```\n./remove-docker-images.sh\n```\n\n### Okta Configuration\n\n#### Delete Person\n\n- In the `Okta Admin Dashboard` main menu on the left, click `Directory` menu and then `People` sub-menu\n- Click `Mario Bros` in the People list\n- In `Mario Bros` profile, click `More Actions` multi-button and then `Deactivate`\n- Confirm deactivation by clicking `Deactivate` button\n- Still in `Mario Bros` profile, click `Delete` button\n- Confirm deletion by clicking `Delete` button\n\n#### Delete Application\n\n- In the `Okta Admin Dashboard` main menu on the left, click `Applications` menu and then `Applications` sub-menu\n- In Application list whose status is `ACTIVE`, click `Simple Service`'s `gear` icon and then click `Deactivate`\n- Confirm deactivation by clicking `Deactivate Application` button\n- In Application list whose status is `INACTIVE`, click `Simple Service`'s `gear` icon and then click `Delete`\n- Confirm deletion by clicking `Delete Application` button\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fokta-springboot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivangfr%2Fokta-springboot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fokta-springboot/lists"}