diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/README.md b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/README.md new file mode 100644 index 000000000..968426f61 --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/README.md @@ -0,0 +1,121 @@ + + +# API Gateway basic-auth Authorizer Function example + +Reviewed: 13.10.2025 + +# When to use this asset? + +Anyone who wants to implement an API Gateway authorizer Function for HTTP basic-auth + +# Author +mikarinneoracle + +# How to use this asset? + +Build and deploy both functions fn-authorizer-auth-basic and fn-authorizer-auth-basic-test under /files to a Function Application in OCI. +

+Create a config for the basicauthorizerfnjava Function: +

+ +

+Config above contains two comma-separated base64 encoded key-value pairs for basic-auth authentication: +

+aGk6aGk=,Zm9vOmJhcg==
+
+ +aGk6aGk= is hi:hi => username is hi, password hi +

+aGk6aGk= is foo:bar => username is foo, password bar +

+(You can modify the config by adding new pairs as you like and remove the existing ones) +

+After deploying the functions add an API Gateway instance and configure the Functions: + +

+ +

+ +Settings for the Single argument authorizer function: +

+Token location: Header +
+Token header name: Authentication + +

+Configure the route for the backend function: + +

+ +

+ +Configure Route Request Policies Header transformations: + + +

+ +Settings for the Header transformations: +

+Behavior: Overwrite +
+Header name: username +
+Values: ${request.auth[username]} +

+ +Test by accessing the API Gateway url from the browse and after the functions have been loaded you should see a basic-auth authentication request popping up. Enter foo and bar and after accepting the backend function should return: + +

+Username: foo
+
+ +# Useful Links + +- [OCI Functions](https://docs.oracle.com/en-us/iaas/Content/Functions/Concepts/functionsoverview.htm) + - Learn how the Functions service lets you create, run, and scale business logic without managing any infrastructure +- [Oracle](https://www.oracle.com/) + - Oracle Website + +### License + +Copyright (c) 2025 Oracle and/or its affiliates. + +Licensed under the Universal Permissive License (UPL), Version 1.0. + +See [LICENSE](https://github.com/oracle-devrel/technology-engineering/blob/main/LICENSE) for more details. diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-config.png b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-config.png new file mode 100644 index 000000000..feac26c60 Binary files /dev/null and b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-config.png differ diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-function.png b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-function.png new file mode 100644 index 000000000..e13cf0a55 Binary files /dev/null and b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/authorizer-function.png differ diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/backend-function.png b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/backend-function.png new file mode 100644 index 000000000..9b86661cf Binary files /dev/null and b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/backend-function.png differ diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/func.yaml b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/func.yaml new file mode 100644 index 000000000..60810d2f3 --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/func.yaml @@ -0,0 +1,7 @@ +schema_version: 20180708 +name: java-hello-world-basic-auth-test +version: 0.0.1 +runtime: java +build_image: fnproject/fn-java-fdk-build:jdk17-1.0.207 +run_image: fnproject/fn-java-fdk:jre17-1.0.207 +cmd: com.example.fn.HelloFunction::handleRequest diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/pom.xml b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/pom.xml new file mode 100644 index 000000000..8ff90a452 --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + UTF-8 + 1.0.207 + + com.example.fn + hello + 1.0.0 + + + + com.fnproject.fn + api + ${fdk.version} + + + com.fnproject.fn + testing-core + ${fdk.version} + test + + + com.fnproject.fn + testing-junit4 + ${fdk.version} + test + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 17 + 17 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + false + + + + + diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/src/main/java/com/example/fn/HelloFunction.java b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/src/main/java/com/example/fn/HelloFunction.java new file mode 100644 index 000000000..d217cca12 --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic-test/src/main/java/com/example/fn/HelloFunction.java @@ -0,0 +1,16 @@ +package com.example.fn; + +import com.fnproject.fn.api.RuntimeContext; +import com.fnproject.fn.api.httpgateway.HTTPGatewayContext; +import com.fnproject.fn.api.InputEvent; + +public class HelloFunction { + + public String handleRequest(final HTTPGatewayContext hctx, final InputEvent input) { + + // Use header transformation in APIGW Route to get username in headers from authorizer + // Overwrite username ${request.auth[username]} + String username = hctx.getHeaders().get("username").orElse(""); + return "Username: " + username; + } +} \ No newline at end of file diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/func.yaml b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/func.yaml new file mode 100644 index 000000000..03f2e1ebc --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/func.yaml @@ -0,0 +1,8 @@ +schema_version: 20180708 +name: basicauthorizerfnjava +version: 0.0.2 +runtime: java +build_image: fnproject/fn-java-fdk-build:jdk17-1.0.207 +run_image: fnproject/fn-java-fdk:jre17-1.0.207 +cmd: com.example.fn.HelloFunction::handleRequest +memory: 1024 diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/pom.xml b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/pom.xml new file mode 100644 index 000000000..8ff90a452 --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + UTF-8 + 1.0.207 + + com.example.fn + hello + 1.0.0 + + + + com.fnproject.fn + api + ${fdk.version} + + + com.fnproject.fn + testing-core + ${fdk.version} + test + + + com.fnproject.fn + testing-junit4 + ${fdk.version} + test + + + junit + junit + 4.12 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 17 + 17 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.1 + + false + + + + + diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/src/main/java/com/example/fn/HelloFunction.java b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/src/main/java/com/example/fn/HelloFunction.java new file mode 100644 index 000000000..ffda2ed6a --- /dev/null +++ b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/fn-authorizer-auth-basic/src/main/java/com/example/fn/HelloFunction.java @@ -0,0 +1,93 @@ +package com.example.fn; + +import com.fnproject.fn.api.FnConfiguration; +import com.fnproject.fn.api.Headers; +import com.fnproject.fn.api.InputEvent; + +import com.fnproject.fn.api.RuntimeContext; +import com.fnproject.fn.api.httpgateway.HTTPGatewayContext; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Base64; +import java.util.List; +import java.util.stream.Collectors; + +public class HelloFunction { + + String authConfig = ""; + + @FnConfiguration + public void setUp(RuntimeContext ctx) throws Exception { + authConfig = ctx.getConfigurationByKey("config").orElse(System.getenv().getOrDefault("config", "")); + } + + public String handleRequest(final HTTPGatewayContext hctx, final InputEvent input) { + + boolean IS_FOUND = false; + String ret = ""; + String username = ""; + + String body = input.consumeBody((InputStream is) -> { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { + return reader.lines().collect(Collectors.joining()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + System.out.println("Body: " + body); + + String[] configTokens = authConfig.split(","); + List tokenizedConfig = Arrays.stream(configTokens).map(String::trim).collect(Collectors.toList()); + + if(body.length() > 0) { + String[] bodyTokens = body.split(","); + List tokenizedBody = Arrays.stream(bodyTokens).map(String::trim).collect(Collectors.toList()); + + for (String configToken : tokenizedConfig) { + for (String token : tokenizedBody) { + if (token.indexOf("Basic ") > -1 && configToken.length() > 0) { + String auth_token = token.substring(token.indexOf("Basic ") + 6, token.indexOf("\"}")); + if (auth_token.equals(configToken)) { + System.out.println("AUTH SUCCESS " + auth_token + " == " + configToken); + byte[] decodedBytes = Base64.getDecoder().decode(auth_token); + String decodedString = new String(decodedBytes); + String[] decodedTokens = decodedString.split(":"); + username = decodedTokens[0]; + IS_FOUND = true; + } else { + System.out.println("AUTH NO MATCH " + auth_token + " <> " + configToken); + } + } + } + } + } + + // Use header transformation in APIGW Route to get username in headers from this response + // in the target function: + // Overwrite username ${request.auth[username]} + if(IS_FOUND) { + LocalDateTime dateTime = LocalDateTime.now().plusDays(1); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'+00:00'"); + String expiryDate = dateTime.format(formatter); + ret = "{ " + + "\"active\": true," + + "\"principal\": \"myprincipal\"," + + "\"scope\": [\"fnbasicauthtest\"]," + + "\"expiresAt\": \"" + expiryDate + "\"," + + "\"context\": { \"username\": \"" + username + "\" }" + + " }"; + } else { + ret = "{ " + + "\"active\": false," + + "\"wwwAuthenticate\": \"Basic realm=\\\"fnbasicauthtest.io\\\"\"" + + " }"; + } + System.out.println(ret); + return ret; + } +} \ No newline at end of file diff --git a/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/header-transformations.png b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/header-transformations.png new file mode 100644 index 000000000..65304dcf2 Binary files /dev/null and b/app-dev/devops-and-containers/functions/java-basic-authorizer-apigw-fn-example/files/header-transformations.png differ diff --git a/app-dev/devops-and-containers/functions/js-authorizer-oci-fn-example/README.md b/app-dev/devops-and-containers/functions/js-authorizer-oci-fn-example/README.md index f285c81a6..02a8088b8 100644 --- a/app-dev/devops-and-containers/functions/js-authorizer-oci-fn-example/README.md +++ b/app-dev/devops-and-containers/functions/js-authorizer-oci-fn-example/README.md @@ -36,13 +36,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> -# API Gateway authorizer function context var example +# API Gateway authorizer Function context var example -Reviewed: 31.10.2024 +Reviewed: 13.10.2025 # When to use this asset? -Anyone who wants to test OCI Queue service using OCI SDK in JavaScript and do this from GitHub Actions. +Anyone who wants to test an API Gateway authorizer Function context var in NodeJS # Author mikarinneoracle