Skip to content

saracalihan/tahakkum

Repository files navigation

Tahakkum

tahakkum logo

tahakküm means domination, sovereignty in Arabic/Turkish. With this RESTFUL API, you can manage your users access to resources, basic or token authentication and authorization, use an OAuth-like registration system, and monitor all these operations to admin and moderator users.

This project does not provide a UI, it is only API.

Except Swagger documentation and authentication ui's like OAuth or OTP

Warning

This project is under development and developed for educational purposes. DON'T USE in the real world!

Table of contents:

Features

  • Username, password authentication
  • Access token authentication
  • access token authentication
  • OAuth token authentication(RESTful, UI)
  • Get user datail with oauth access token
  • User CRUD
  • OTP, TOTP authentication(RESTful, UI)
  • User role CRUD(a user has two roles, first is role related authorization and second is custom role like dealer, teacher, etc.)
  • Authorization(path and role based)
  • User blacklist for authorization
  • One time accessable resources(paths)
  • Operation monitoring(user's login attempts, user's tokens, routes and access couses)

Setup

This project is fully Dockerized. We use Docker and Docker Compose. We don't have any fancy build steps. Just create a container then run it.

Install

Clone this project using GIT

git clone git@github.com:saracalihan/tahakkum.git

Go into directory

cd tahakkum

Build and Run

The api is already dockerized and we use postgre images with it. We are porting 3000 ports to the host machine so the 3000 ports must be free or you need to change the port in the docker-compose.yaml file.

This command builds and runs the api then bridges it with postgres:

# docker-compose up
docker compose up

if you dont want to use docker, you build and run manually with those commands:

# compile, this command create jar file in to target folder
./mvnw compile package
# execute jar file, you have to set environment variables. See sample.env file
java -jar ./target/*.jar

Architecture

Userflow

Authentication

This is a basic user authentication unit.

Firstly, the client should register itself with name, username, email, role, and password data to /authentication/register. If the api created user successfully, the api sent back data to the client can check it.

Then, the client can log in with username(or email, key name must be username) and password on the /authentication/login. If login is successful, server send user data(without hidden like password_hash, password_salt) and access token, else api send the reason why clients don't log in.

Now, the client has an access token and can access to all non-public routes pass this token in the header.

Also, the client gets the token's data(expireAt, status, etc.) /authentication/me if the token is not expired or canceled.

OAuth

If you don't store users on Tahakkum but want other Tahakkum users can log easyly in to your system u can use Tahakkum's OAuth system. You say what information you need then if the user login successfully we send an access token which u can access that information.

Firstly, You have to create an oauth app with a personal access token, if you don't have an access token please log in. Pass your application's name, description(optional), homepage(optional), photo(optional), scope(wanted user fields, id, name, username, email. Ex.: "name, email") and redirect_url (you can use HTTP or HTTPS) to /oauth2/register-app. The api response isclient_id and client_secret tokens.

An example of Tahakkum's OAuth interface:

Login1

Then, send a GET request to /oauth2/auth?client_id=<your_id>&client_secret=<your_secret>. If these secret values are valid, you get an HTML file and show it to your user. If the user can log in successfully, we redirect him to the redirect_url with access_token value on the query. For example, if your redirect url is http://abc.com/login-with-tahakkum, the user was redirected to the http://abc.com/login-with-tahakkum?access_token=XXXX.

After you handle the request and get to the oauth access token, send GET request to the /oauth2/user-info url with x-access-token header.

Example:

GET /oauth2/user-info
"content-type": "application/json"
"x-access-token": "XXXX"

After successfully logged in:

login-redirect

If user enter wrong data:

login-fail

An app without any description, logo and homepage:

Login2

One Time Password

If you want to use two-step verification in your system, you should send single-use codes to users using methods such as mail, sms or 2 Factor Authenticator.

You can automate the steps of creating codes, sending codes and verifying codes with Tahakkum.

OPT

First, after logging in with a developer account, you need to create an OTP Application with the given x-access-token. When creating the application, it is sufficient to send the name of the application, the address to which we will send the code when the code is created, the method, the body, query and header values ​​​​if any, the user information when the code verification is successful and unsuccessful, and theaddress to which we will send the GET request request to /otp/register-app with the POST method. In response, with the 201 status code,

The code redirection process is completely dynamically managed thanks to codeRedirect information. Once the code is created, you can send REST requests in the format requested by your service providers such as mail, sms or 2 Factor Authenticator and send the code to your user.

When you write the __id__, __code__, __secret__ and __verifyUrl__ values ​​in a field other than codeRedirectMethod within the codeRedirect values, Tahakkum automatically replaces these words with values ​​specific to that user in the request it makes.

To create a code, you can send the client_id, client_secret values ​​of your application to /otp with the POST method and your user's tracking metadata content if you wish. It returns the id, secret, verifyUrl information of the code with the 201 code and sends the request to the codeRedirect address.

If the mail or SMS request return error*, we will send you back the message returned by that server with a 400 error code and a body in the form of status, message and the generated code will be cancelled.

The code is valid for 72 hours. After this period, the code is expired.

If you want to verify a code, send the code, id and secret values ​​to /otp/verify with the POST method. If the operation is successful, you will be returned with 200 status code and metadata information, if not, you will be given a 401 status code

TOPT

Time based one time code, the operations are carried out in the same way as otp.

To generate the code, send the time depth to /otp/time-based as seconds(2 seconds will be added to this time for the network delay that will occur during the transmission of the code). To verify the code, send a request to /otp/time-based/verify.

Important Note In both otp and totp processes, an interface URL that you can use to verify the code is sent to you. Instead of using verify endpoints, you can redirect your users directly to this address.

Endpoints

For more details, run the project and sen GET request to /docs endpoint.

Authentication Endpoints

Register

Method: POST Path: /authentication/register Body:

{
  name: "string",
  username: "string",
  email: "string",
  password: "string",
  passwordAgain: "string"
}

response:

{
  name: "string",
  username: "string",
  email: "string",
  password: "string",
  passwordAgain: "string",
  createdAt: "Date",
  updatedAt: null,
}

status: 201 or 400

Login

Method: POST Path: /authentication/login Body:

{
  username: "string", // you can pass username or email as a value
  password: "string",
}

response:

{
  user: {
    id: "number"
    name: "string",
    username: "string",
    email: "string",
    createdAt: "Date",
    updatedAt: null,
  },
  token:{
    value: "string",
    type: "AccessToken",
    status: "Active",
    expireAt: "Date",
    createdAt: "Date",
    updatedAt: "Date",
  }
}

status: 200 or 400

Me

Method: GET Path: /authentication/me Header:

{
  "x-access-token": "string" // your access token
}

response:

{
  user: {
    id: "number"
    name: "string",
    username: "string",
    email: "string",
    createdAt: "Date",
    updatedAt: null,
  },
  token:{
    value: "string",
    type: "AccessToken",
    status: "Active",
    expireAt: "Date",
    createdAt: "Date",
    updatedAt: "Date",
  }
}

status: 200 or 401

OAuth Endpoints

Register App

Method: POST Path: /oauth2/register-app Header:

{
  "x-access-token": "string" // your access token
}

Body:

{
  name: "string",
  redirectUrl: "string",
  scopes: [
    "string", // id, email, name, username
  ]
  description: "string", // optional
  homePage: "string", // optional
  photo: "string", // optional
}

response:

{
  id: "Long"
  clientSecret: "string"
  clientId: "string"
  name: "string"
  homepage: "string"
  photo: "string"
  description: "string"
  scopes: ["string"]
  redirectUrl: "string"
  owner: "User"
  createdAt: "date"
  updatedAt: "date"
  tokens: ["object"]
}

status: 201, 400 or 401

OAuth

Method: GET Path: /oatuh2/oauth Query:

{
  client_id: "string" // your app's client_id
  client_secret: "string" // your app's client_secret
}

response:

// this page return the oauth login html file
// That file redirect user to the app's redirect_url adress with access_token query

status: 301, 400 or 401

Get User Info

Method: GET Path: /oatuh2/user-info Header:

{
  "x-access-token": "string"// oauth access token
}

response:

// this route return the user's selected fields based on app's scopes data

status: 200 or 401

Refresh Token
Login(internal use)

Method: POST Path: /oatuh2/login Query:

{
  "token": "string"// validation token, generated by the server
}

Body:

{
  username: "string",
  password: "string"
}

response:

// This route redirect the client to the app's redirect_url adress with access_token query

status: 301 or 401

Authentication Endpoints

Register

Method: POST Path: /authentication/register Body:

{
  name: "string",
  username: "string",
  email: "string",
  password: "string",
  passwordAgain: "string"
}

response:

{
  name: "string",
  username: "string",
  email: "string",
  password: "string",
  passwordAgain: "string",
  createdAt: "Date",
  updatedAt: null,
}

status: 201

Login
Me

OTP

Register OTP App

Method: POST Path: /otp/register-app Header:

{
  "x-access-token": "string" // your access token
}

Body:

{
  name: "string",
  redirectUrl: "string"
  failRedirectUrl: "string"
  codeRedirectUrl: "string"
  codeRedirectMethod: "GET|POST|PUT|DELETE"
  codeRedirectHeader: {}
  codeRedirectBody: {}
}

response:

{
  id: 123
  clientSecret: "string"
  clientId: "string"
  name: "string"
  redirectUrl: "string"
  failRedirectUrl: "string"
  codeRedirectUrl: "string"
  codeRedirectMethod: "string"
  codeRedirectHeader: {}
  codeRedirectBody: {}
  createdAt: "Date"
  updatedAt: "Date"
}

status: 201

Create OTP Code

Method: POST Path: /otp?client_id=<your_id>&client_secret=<your_secret> Body:

{
  // metadata, we send it back when otp verification is success
}

response:

{
  id: "string",
  secret: "string",
  validateUrl: "string"
}

status: 201

Verify OTP Code

Method: POST Path: /otp/verify Body:

{
  id: "string",
  secret: "string",
  code: "string"
}

response:

{
  otpId: "string"
  otpSecret: "string"
  code: 123456
  metadatas: {}
  status: "Success"
  type: "OTP"
  expiredAt: "Date"
  createdAt: "Date"
  updatedAt: "Date"
}

status: 200

Create TOTP Code

Method: POST Path: /otp/time-based?client_id=<your_id>&client_secret=<your_secret> Body:

{
  time: 180, // second
  metadata: {
    // we send it back when otp verification is success
  }
}

response:

{
  id: "string",
  secret: "string",
  validateUrl: "string",
  expireAt: "Date"
}

status: 201

Verify TOTP Code

Method: POST Path: /otp/time-based/verify Body:

{
  id: "string",
  secret: "string",
  code: "string"
}

response:

{
  otpId: "string"
  otpSecret: "string"
  code: 123456
  metadatas: {}
  status: "Success"
  type: "TOTP"
  expiredAt: "Date"
  createdAt: "Date"
  updatedAt: "Date"
}

status: 200

Database

db diagram

Todo: Not implemented yet!

Folder Structure

.
├── docker-compose.yaml # docker compose file
├── Dockerfile # docker file
├── LICENSE # GNU GPLv3 license
├── mvnw
├── mvnw.cmd
├── pom.xml
├── README.md
├── sample.env # example environment file, real file is `.env`
├── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── tahakkum
    │   │               ├── Application.java
    │   │               ├── config
    │   │               │   ├── AppConfig.java
    │   │               │   └── EmptyObjectSerializer.java
    │   │               ├── constant
    │   │               │   ├── Constants.java
    │   │               │   ├── OTPStatus.java
    │   │               │   ├── OTPTypes.java
    │   │               │   ├── OTPVariables.java
    │   │               │   ├── Roles.java
    │   │               │   ├── TokenStatuses.java
    │   │               │   └── TokenTypes.java
    │   │               ├── controller
    │   │               │   ├── AuthenticationController.java
    │   │               │   ├── MainController.java
    │   │               │   ├── OAuthController.java
    │   │               │   └── OneTimePasswordController.java
    │   │               ├── dto
    │   │               │   ├── authentication
    │   │               │   │   ├── LoginDto.java
    │   │               │   │   ├── LoginResponseDto.java
    │   │               │   │   └── RegisterDto.java
    │   │               │   ├── oauth
    │   │               │   │   └── request
    │   │               │   │       └── AppRegister.java
    │   │               │   └── otp
    │   │               │       ├── request
    │   │               │       │   ├── OTPVerifyDto.java
    │   │               │       │   ├── RegisterAppDto.java
    │   │               │       │   └── TOTPCreateDto.java
    │   │               │       └── response
    │   │               │           ├── OtpDto.java
    │   │               │           └── TotpDto.java
    │   │               ├── exception
    │   │               │   └── ResponseException.java
    │   │               ├── handler
    │   │               │   └── GlobalExceptionHandler.java
    │   │               ├── model
    │   │               │   ├── OAuthApp.java
    │   │               │   ├── OAuthToken.java
    │   │               │   ├── OTPApp.java
    │   │               │   ├── OTPCode.java
    │   │               │   ├── Role.java
    │   │               │   ├── Token.java
    │   │               │   └── User.java
    │   │               ├── repository
    │   │               │   ├── OAuthAppRepository.java
    │   │               │   ├── OAuthTokenRepository.java
    │   │               │   ├── OTPAppRepository.java
    │   │               │   ├── OTPCodeRepository.java
    │   │               │   ├── TokenRepository.java
    │   │               │   └── UserRepository.java
    │   │               ├── serializer
    │   │               │   └── ResponseExceptionSerializer.java
    │   │               ├── service
    │   │               │   ├── AuthService.java
    │   │               │   ├── OTPService.java
    │   │               │   ├── TokenService.java
    │   │               │   └── UserService.java
    │   │               ├── template
    │   │               │   ├── oauth.html
    │   │               │   ├── otp.html
    │   │               │   └── totp.html
    │   │               └── utility
    │   │                   ├── Common.java
    │   │                   ├── Cryptation.java
    │   │                   └── UIBuilder.java
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       │   └── tahakkum-logo.png
    │       └── templates
    └── test

Contributing

Rules

If you want to contribute to the project, please first check if the work you are doing is already an issue. If there is an issue and there is someone assigned to the issue, contact that person. If there is no issue, you can send your development to the project managers by opening a pull request. Please read CONTRIBUTING.md

Development

Todo: Not implemented yet!

Contributors

License

This project is under the GPLv3 license. Also, use Maven's license policy.

About

999 in 1 custom RESTful auth server(OAuth, (T)OTP, basic/token auth, RBAC, User Control)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors