Skip to content

Commit

Permalink
✨ feat: add Auth4j for support header request #4
Browse files Browse the repository at this point in the history
  • Loading branch information
pnguyen215 committed Jun 8, 2024
1 parent 625e6c6 commit eee2d15
Show file tree
Hide file tree
Showing 8 changed files with 1,578 additions and 0 deletions.
115 changes: 115 additions & 0 deletions docs/003_Auth4j.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Auth4j

`Auth4j` is a class utility designed to handle various types of authentication mechanisms. It supports Basic, Bearer, API
Key, OAuth2, and OAuth2 Client Credentials authentication types.

## Features

- Basic Authentication
- Bearer Token Authentication
- API Key Authentication
- OAuth2 Authentication
- OAuth2 Client Credentials Authentication

## Usage

### Basic Authentication

```java
Auth4j auth = new Auth4j.Builder()
.type(AuthType.BASIC)
.username("yourUsername")
.password("yourPassword")
.build();

WrapResponse<?> response = auth.verify();
if (response.isSuccess()) {
Map<String, String> headers = auth.getHeaders();
// Use headers in your HTTP request
}
```

### Bearer Token Authentication

```java
Auth4j auth = new Auth4j.Builder()
.type(AuthType.BEARER)
.token("yourBearerToken")
.build();

WrapResponse<?> response = auth.verify();
if (response.isSuccess()) {
Map<String, String> headers = auth.getHeaders();
// Use headers in your HTTP request
}
```

### API Key Authentication

```java
Auth4j auth = new Auth4j.Builder()
.type(AuthType.API_KEY)
.headerNameApiKey("X-API-KEY")
.apiKey("yourApiKey")
.build();

WrapResponse<?> response = auth.verify();
if (response.isSuccess()) {
Map<String, String> headers = auth.getHeaders();
// Use headers in your HTTP request
}
```

### OAuth2 Authentication

```java
Auth4j auth = new Auth4j.Builder()
.type(AuthType.OAUTH2)
.accessToken("yourAccessToken")
.build();

WrapResponse<?> response = auth.verify();
if (response.isSuccess()) {
Map<String, String> headers = auth.getHeaders();
// Use headers in your HTTP request
}
```

### OAuth2 Client Credentials Authentication

```java
AuthFactory authFactory = new AuthFactory() {
@Override
public String retrieveAccessToken(String clientId, String clientSecret) {
// Implement your logic to retrieve the access token
return "yourAccessToken";
}
};

Auth4j auth = new Auth4j.Builder()
.type(AuthType.OAUTH2_CLIENT_CREDENTIALS)
.factory(authFactory)
.clientId("yourClientId")
.clientSecret("yourClientSecret")
.build();

WrapResponse<?> response = auth.verify();
if (response.isSuccess()) {
Map<String, String> headers = auth.getHeaders();
// Use headers in your HTTP request
}
```

### Custom Authentication Logic

To implement custom logic for retrieving the access token in the OAuth2 Client Credentials flow, you can extend the AuthFactory and provide your implementation.

```java
public class CustomAuthFactory extends AuthFactory {
@Override
public String retrieveAccessToken(String clientId, String clientSecret) {
// Custom logic to retrieve the access token
return "yourAccessToken";
}
}
```
129 changes: 129 additions & 0 deletions plugin/src/main/groovy/org/unify4j/common/Auth4j.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package org.unify4j.common;

import org.unify4j.model.builder.HttpWrapBuilder;
import org.unify4j.model.c.HttpHeaders;
import org.unify4j.model.enums.AuthType;
import org.unify4j.model.onlyrd.AbstractAuthClass;
import org.unify4j.model.response.WrapResponse;

import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class Auth4j extends AbstractAuthClass {
protected Auth4j(Builder builder) {
super(builder);
}

/**
* @return a WrapResponse<?> object containing the response from the Auth manager API, class {@link WrapResponse}
*/
@Override
public WrapResponse<?> verify() {
if (this.type == null) {
return new HttpWrapBuilder<>().badRequest("Auth Type is required").build();
}
switch (this.type) {
case BASIC:
if (String4j.isEmpty(this.username)) {
return new HttpWrapBuilder<>().badRequest("Username is required").build();
}
if (String4j.isEmpty(this.password)) {
return new HttpWrapBuilder<>().badRequest("Password is required").build();
}
break;
case BEARER:
if (String4j.isEmpty(this.token)) {
return new HttpWrapBuilder<>().badRequest("Token is required").build();
}
break;
case API_KEY:
if (String4j.isEmpty(this.headerNameApiKey)) {
return new HttpWrapBuilder<>().badRequest("Header name API-KEY is required").build();
}
if (String4j.isEmpty(this.apiKey)) {
return new HttpWrapBuilder<>().badRequest("API-KEY is required").build();
}
break;
case OAUTH2:
if (String4j.isEmpty(this.accessToken)) {
return new HttpWrapBuilder<>().badRequest("Access-Token is required").build();
}
break;
case OAUTH2_CLIENT_CREDENTIALS:
if (this.factory == null) {
return new HttpWrapBuilder<>().badRequest("AuthFactory is required for OAUTH2_CLIENT_CREDENTIALS").build();
}
if (String4j.isEmpty(this.clientId)) {
return new HttpWrapBuilder<>().badRequest("Client-Id is required").build();
}
if (String4j.isEmpty(this.clientSecret)) {
return new HttpWrapBuilder<>().badRequest("Client-Secret is required").build();
}
break;
}
return new HttpWrapBuilder<>().ok(null).build();
}

/**
* @return map header request, class {@link Map}
*/
@Override
public Map<String, String> getHeaders() {
WrapResponse<?> verified = this.verify();
if (!verified.isSuccess()) {
return Collections.emptyMap();
}
Map<String, String> header = new HashMap<>();
switch (this.type) {
case BASIC:
String authValue = Base64.getEncoder().encodeToString(String.format("%s:%s", this.username, this.password).getBytes());
header.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", String4j.capitalizeEachWords(AuthType.BASIC.name()), authValue));
break;
case BEARER:
header.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", String4j.capitalizeEachWords(AuthType.BEARER.name()), this.token));
break;
case API_KEY:
header.put(this.headerNameApiKey, this.apiKey);
break;
case OAUTH2:
header.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", String4j.capitalizeEachWords(AuthType.BEARER.name()), this.accessToken));
break;
case OAUTH2_CLIENT_CREDENTIALS:
this.accessToken = this.factory.retrieveAccessToken(this.clientId, this.clientSecret);
header.put(HttpHeaders.AUTHORIZATION, String.format("%s %s", String4j.capitalizeEachWords(AuthType.BEARER.name()), this.accessToken));
break;
default:
throw new IllegalArgumentException(String.format("Unsupported Auth Type: %s", this.type.name()));
}
return header;
}

/**
* @return the string includes information
*/
@Override
public String toString() {
return String.format("Auth4j { type: %s, username: %s, password: %s, token: %s, api_key: %s, header_name_api_key: %s, client_id: %s, client_secret: %s, access_token: %s, refresh_token: %s }",
this.type, this.username, String4j.isEmpty(this.password) ? "" : "***", this.token, this.apiKey, this.headerNameApiKey, this.clientId, this.clientSecret, this.accessToken, this.refreshToken);
}

public static class Builder extends AbstractAuthClass.Builder<Builder> {
/**
* @return new instance Auth, class {@link Auth4j}
*/
@Override
public Auth4j build() {
return new Auth4j(this);
}

/**
* @return the current self, class {@link Builder}
*/
@Override
protected Builder self() {
return this;
}
}
}
26 changes: 26 additions & 0 deletions plugin/src/main/groovy/org/unify4j/common/Vi4j.java
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,30 @@ public static void throwIfTrue(boolean logic, String message) {
throw new IllegalArgumentException(message);
}
}

/**
* Throws an IllegalStateException if the provided logic condition is true.
*
* @param logic The boolean condition to evaluate.
* @param message The message to include in the exception if the condition is true.
* @throws IllegalStateException if the logic condition is true.
*/
public static void throwStateIfTrue(boolean logic, String message) {
if (logic) {
throw new IllegalStateException(message);
}
}

/**
* Throws an IllegalStateException if the provided logic condition is false.
*
* @param logic The boolean condition to evaluate.
* @param message The message to include in the exception if the condition is false.
* @throws IllegalStateException if the logic condition is false.
*/
public static void throwStateIfFalse(boolean logic, String message) {
if (!logic) {
throw new IllegalStateException(message);
}
}
}
Loading

0 comments on commit eee2d15

Please sign in to comment.