Skip to content

Instantly share code, notes, and snippets.

@dzmitry-savitski
Last active June 24, 2025 17:35
Show Gist options
  • Select an option

  • Save dzmitry-savitski/0c9c7f54ad8c1c87fad44fa9b28924a7 to your computer and use it in GitHub Desktop.

Select an option

Save dzmitry-savitski/0c9c7f54ad8c1c87fad44fa9b28924a7 to your computer and use it in GitHub Desktop.

Revisions

  1. dzmitry-savitski revised this gist Jun 24, 2025. 1 changed file with 31 additions and 23 deletions.
    54 changes: 31 additions & 23 deletions ig
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,36 @@
    import org.forgerock.http.protocol.Request
    import org.forgerock.http.protocol.Response
    import org.forgerock.http.protocol.Form
    import org.forgerock.http.protocol.UrlEncodedFormEntity
    import java.time.Instant
    import java.time.format.DateTimeFormatter
    import java.util.UUID
    import javax.crypto.Mac
    import javax.crypto.spec.SecretKeySpec
    import org.forgerock.util.encode.Base64

    // Build form with credentials
    def form = new Form()
    form.add("grant_type", "client_credentials")
    form.add("client_id", "my-client-id")
    form.add("client_secret", "my-client-secret")
    form.add("scope", "my-scope")
    def SECRET = "my-super-secret-key" // 🔐 Replace with real shared secret

    // Build request
    def req = new Request()
    req.setMethod("POST")
    req.setUri("https://auth.example.com/oauth2/token")
    req.getHeaders().add("Content-Type", "application/x-www-form-urlencoded")
    req.setEntity(new UrlEncodedFormEntity(form))

    // Send the request and handle the response
    http.send(req).thenAccept { Response externalResp ->
    def status = externalResp.getStatus()
    def body = externalResp.getEntity().getString()
    logger.info("Token endpoint responded with status $status")
    logger.info("Body: $body")
    String computeSignature(String method, String path, String timestamp, String nonce, String body, String secret) {
    String data = "${method.toUpperCase()}\n${path}\n${timestamp}\n${nonce}\n${body}"
    SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256")
    Mac mac = Mac.getInstance("HmacSHA256")
    mac.init(keySpec)
    byte[] hmacBytes = mac.doFinal(data.getBytes("UTF-8"))
    return Base64.encode(hmacBytes)
    }

    def timestamp = DateTimeFormatter.ISO_INSTANT.format(Instant.now())
    def nonce = UUID.randomUUID().toString()
    def method = request.method
    def path = request.uri.path
    def body = request.entity?.string ?: ""

    // Calculate signature
    def signature = computeSignature(method, path, timestamp, nonce, body, SECRET)

    // Add headers
    request.headers.add("X-Timestamp", timestamp)
    request.headers.add("X-Nonce", nonce)
    request.headers.add("X-API-Key", "your-key-id") // or use env/config
    request.headers.add("X-Signature", signature)

    logger.info("HMAC Signature Added: ${signature}")

    return next.handle(context, request)
  2. dzmitry-savitski revised this gist Jun 16, 2025. 1 changed file with 24 additions and 24 deletions.
    48 changes: 24 additions & 24 deletions ig
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,28 @@
    import org.forgerock.http.protocol.*
    import org.forgerock.openig.http.*
    import org.forgerock.http.protocol.Request
    import org.forgerock.http.protocol.Response
    import org.forgerock.http.protocol.Form
    import org.forgerock.http.protocol.UrlEncodedFormEntity

    // Replace with your actual values
    def clientId = "my-client-id"
    def clientSecret = "my-client-secret"
    def tokenEndpoint = "https://am.example.com/oauth2/access_token"
    // Build form with credentials
    def form = new Form()
    form.add("grant_type", "client_credentials")
    form.add("client_id", "my-client-id")
    form.add("client_secret", "my-client-secret")
    form.add("scope", "my-scope")

    // Prepare request
    def tokenRequest = new Request()
    tokenRequest.uri = tokenEndpoint
    tokenRequest.method = "POST"
    tokenRequest.headers.put("Content-Type", "application/x-www-form-urlencoded")
    tokenRequest.entity = "grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}"
    // Build request
    def req = new Request()
    req.setMethod("POST")
    req.setUri("https://auth.example.com/oauth2/token")
    req.getHeaders().add("Content-Type", "application/x-www-form-urlencoded")
    req.setEntity(new UrlEncodedFormEntity(form))

    // Send the request using IG's internal HTTP client
    def response = client.call(tokenRequest)

    // Parse the access token
    if (response.status.successful) {
    def json = new JsonSlurper().parseText(response.entity.string)
    def accessToken = json.access_token
    logger.info("Got token: " + accessToken)
    return new Response(Status.OK).setEntity("Access token: ${accessToken}")
    } else {
    logger.error("Token request failed: ${response.status}")
    return new Response(Status.UNAUTHORIZED).setEntity("Failed to get token")
    // Send the request and handle the response
    http.send(req).thenAccept { Response externalResp ->
    def status = externalResp.getStatus()
    def body = externalResp.getEntity().getString()
    logger.info("Token endpoint responded with status $status")
    logger.info("Body: $body")
    }

    return next.handle(context, request)
  3. dzmitry-savitski created this gist Jun 16, 2025.
    28 changes: 28 additions & 0 deletions ig
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    import org.forgerock.http.protocol.*
    import org.forgerock.openig.http.*

    // Replace with your actual values
    def clientId = "my-client-id"
    def clientSecret = "my-client-secret"
    def tokenEndpoint = "https://am.example.com/oauth2/access_token"

    // Prepare request
    def tokenRequest = new Request()
    tokenRequest.uri = tokenEndpoint
    tokenRequest.method = "POST"
    tokenRequest.headers.put("Content-Type", "application/x-www-form-urlencoded")
    tokenRequest.entity = "grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}"

    // Send the request using IG's internal HTTP client
    def response = client.call(tokenRequest)

    // Parse the access token
    if (response.status.successful) {
    def json = new JsonSlurper().parseText(response.entity.string)
    def accessToken = json.access_token
    logger.info("Got token: " + accessToken)
    return new Response(Status.OK).setEntity("Access token: ${accessToken}")
    } else {
    logger.error("Token request failed: ${response.status}")
    return new Response(Status.UNAUTHORIZED).setEntity("Failed to get token")
    }