Ron and Ella Wiki Page

Extremely Serious

Page 11 of 33

The Resource Owner Password Credential (ROPC) Grant Type

The resource owner password credential grant type is designed as a stop-gap for legacy applications. Should only be used temporarily until the migration of the application to OAUTH is complete. This grant type should never be used anymore. This type can request for offline_access scope (i.e. to request for refresh token).

  1. Use the token end point to do post request for the access token with the following headers:

    Content-Type = application/x-www-form-urlencoded

    And with the following form data:

    grant_type = password
    client_id = the one used from step 1.
    client_secret = 
    username = 
    password = 
    scope = (Optional) what permision wanted. If not specified, default permission will be given.
    state = (Optional) value to echo to us.

    Expected Response

    {
    "access_token" : <ACCESS_TOKEN>,
    "token_type" : "Bearer",
    "expires_in" : 3600,
    "scope" : <The scope allowed by the server>
    }
  2. Call the API with the authorization header like the following syntax:

    Bearer <ACCESS_TOKEN>

Related Post
KEYCLOAK – JWT GENERATION – PASSWORD GRANT TYPE

Keycloak – Realm – OpenID Configuration

The open id configuration exposes some information like the following:

  • Authorization endpoint
  • Token endpoint
  • Supported grant types
  • Supported response types
  • Supported response modes
  • Supported claims
  • Supported scopes

Use the following address syntax to find-out the OpenID configuration:

<KEYCLOAK_ADDRESS>/realms/<TARGET_REALM>/.well-known/openid-configuration

Example

Given

Token Value
KEYCLOAK_ADDRESS http://localhost:8080
TARGET_REALM test

The OpenID configuration would be:

http://localhost:8080/realms/testrealm/.well-known/openid-configuration

Keycloak – JWT Generation – Password Grant Type

Pre-requisite

  • Keycloak 19^1

Creating a New Client and User

  1. Sign in to keycloak admin console using the following address:

    Must know a valid credential.

    http://localhost:8080/admin/

  2. Switch or create a realm that is NOT a master realm (i.e. leave the master realms for keycloak usage only), like the following (i.e. jwtrealm):
    jwt-realm

  3. Create a new client as follows:

    1. Ensure that OpenID Connect is the Client type.

    2. Provide a Client ID (e.g. jwtclient).

    3. Click the Next button.

      client-general-settings

    4. Enable the Client authentication.

    5. In the Authentication flow, unselect the standard flow.

    6. Click the Save button.

      client-capability-config

  4. Create a new user as follows:

    1. Fill-in the username field (e.g. testuser).

    2. Click the Create button.

      user-create

    3. Click the Credentials tab.

    4. Click the Set password button.

    5. Fill-in the Password field.

    6. Fill-in the Password confirmation field.

    7. Turn-off temporary.

    8. Click the Save button.

      user-password

    9. Click the Save password button.

Using Postman for Testing

  1. Create a post request to the following address format:

    http://localhost:8080/realms/<TARGET_REALM>/protocol/openid-connect/token

    Example

    Using the jwtrealm as the TARGET_REALM (i.e. configured in the previous section).

    http://localhost:8080/realms/jwtrealm/protocol/openid-connect/token

  2. Click the Body tab.

  3. Select x-www-form-url-encoded.

  4. Add the following entries:

    Key Value Comment
    client_id jwtclient This is the client configured earlier.
    grant_type password This is for direct access grant type.
    client_secret <Client secret> This can be found in the jwtclient (i.e. configured earlier) client credentials tab.

    client-secret

    scope openid The openid scope is required; to indicate that the application intends to use OIDC to verify the user's identity.
    username testuser This is the user configured earlier.
    password <password> This is the password for the user that is configured earlier.
  5. Click the Send button.

    postman-request

Success Output

The success output is in the following format.

{
    "access_token": "The access token.",
    "expires_in": "Access token expiration.",
    "refresh_expires_in": "Refresh token expiration",
    "refresh_token": "The refresh token.",
    "token_type": "Bearer",
    "id_token": "The ID token.",
    "not-before-policy": 0,
    "session_state": "The session state.",
    "scope": "openid profile email"
}

You paste the encoded token to the following website to decode its content:

https://jwt.io/

Invalid Credential Output

{
    "error": "invalid_grant",
    "error_description": "Invalid user credentials"
}

Related Post
THE RESOURCE OWNER PASSWORD CREDENTIAL (ROPC) GRANT TYPE

Windows Shutdown and Restart Event IDs

The event IDs that can be searched in windows event viewer (i.e. Windows Logs -> System) for the confirmation of shutdown or restart.

Event ID Name Description
14 The system has rebooted without cleanly shutting down first This event indicates that some unexpected activity prevented Windows from shutting down correctly. Such a shutdown might be caused by an interruption in the power supply or by a Stop error. If feasible, Windows records any error codes as it shuts down.
1074 System has been shutdown by a process/user. This event is written when an application causes the system to restart, or when the user initiates a restart or shutdown by clicking Start or pressing CTRL+ALT+DELETE, and then clicking Shut Down.
6006 The event log service was stopped. The event is logged at boot time noting that the Event Log service was stopped.
6008 Unexpected system shutdown The previous system shutdown at Time on
Date was unexpected.

Authorization Code Grant Type

The authorization code grant type is designed for confidential clients (e.g. websites with a server back end) that can keep a secret. This type can request for offline_access scope (i.e. to request for refresh token).

  1. Use the authorization end point to request the authorization code with the following query parameters:

    response_type = code 
    client_id = the client unique code
    redirect_uri = redirection URL.
    state = (Optional) value to echo to us.
    scope = (Optional) what permision wanted. If not specified, default permission will be given.
    response_mode = (Optional) query

    A login form will be displayed if not yet filled-up before.

    Expected Response

    The redirect_uri with the following query parameters:

    code = The authorization code
    state = state value if given.
  2. Use the token end point to do post request for the access token with the following headers:

    Content-Type = application/x-www-form-urlencoded
    Authorization = Basic <CREDENTIAL>

    And with the following parameters:

    grant_type = authorization_code.
    code = The authorization code from step 1.
    redirect_uri = The used from step 1.

    Expected Response

    Header

    Content-Type: application/json
    
    {
    "access_token" : <ACCESS_TOKEN>,
    "token_type" : "Bearer",
    "expires_in" : 3600,
    "scope" : <The scope allowed by the server>
    }
  3. Call the API with the authorization header like the following syntax:

    Bearer <ACCESS_TOKEN>

Sample implementation can be found here.

Gradle Binary to Package with the Wrapper

  1. Download the gradle binary from the following address:

    https://services.gradle.org/distributions/

    For example gradle-7.4-all.zip.

  2. Place the downloaded gradle binary to the gradle/wrapper directory of the gradle project.

  3. Update the wrapper configuration (i.e. gradle/wrapper/gradle-wrapper.properties) like the following:

    If you've downloaded gradle-7.4-all.zip binary from step 1.

    distributionBase=PROJECT
    distributionPath=wrapper/dists
    distributionUrl=gradle-7.4-all.zip
    zipStoreBase=PROJECT
    zipStorePath=wrapper/dists

Java UTF-16LE Base64 CODEC

The UTF-16LE base64 encoding is compatible to be used with powershell's encoded command.

Encoding

//The text to encode.
var command = "Write-Output \"Hello World\"";
var encodedString = Base64.getEncoder().encodeToString(command.getBytes(StandardCharsets.UTF_16LE));
System.out.printf("Base64: %s%n", encodedString);

Output

Base64: VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAiAEgAZQBsAGwAbwAgAFcAbwByAGwAZAAiAA==

The preceding output can be used with powershell like the following:

powershell -encodedcommand VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAiAEgAZQBsAGwAbwAgAFcAbwByAGwAZAAiAA==

Decoding

//The base64 text to decode.
var base64="VwByAGkAdABlAC0ATwB1AHQAcAB1AHQAIAAiAEgAZQBsAGwAbwAgAFcAbwByAGwAZAAiAA==";
byte[] decodedBytes = Base64.getDecoder().decode(base64);
String decodedString = new String(decodedBytes, StandardCharsets.UTF_16LE);
System.out.printf("Decoded: %s%n", decodedString);

Output

Decoded: Write-Output "Hello World"

Mocking Static Method with Mockito

Sample codes for mocking a static with Mockito.

The StringUtil class is a very trivial class that converts the text to all capitalized.

StringUtil class

public final class StringUtil {

    private StringUtil() {}

    public static String upperCase(String text) {
        return text.toUpperCase();
    }
}

Mocking the StringUtil.upperCase method

Stubbing the StringUtil.upperCase method to return test if test is passed as argument.

Dependencies Required

org.junit.jupiter:junit-jupiter-engine:5.8.2
org.mockito:mockito-inline:4.4.0

StringUtilTest class

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

public class StringUtilTest {

    @Test
    void staticMethod() {
        try (var utilities = mockStatic(StringUtil.class)) {
            utilities.when(() -> StringUtil.upperCase("test")).thenReturn("test");
            assertEquals("test", StringUtil.upperCase("test"));
        }
    }
}

Checking if a Directory is Empty Using Stream

var dirPath = Paths.get("C:\\tmp", "sample"); //The path to be tested.
if (dirPath.toFile().isDirectory()) { //Check if the directory exists.
    try (Stream<Path> entries = Files.list(dirPath)) {
        if (entries.findFirst().isEmpty()) {
            System.out.printf("%s is empty.", dirPath);
        }
    }
}
« Older posts Newer posts »