Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jans-cedarling): create uniffi binding for cedarling with sample ios app using it #10816

Merged
merged 26 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b53e0fd
feat: initial commit for ios binding
duttarnab Feb 9, 2025
5a37e67
feat: commiting remaining files
duttarnab Feb 9, 2025
55aa63d
feat: pushing uniffi-bindgen.rs file
duttarnab Feb 9, 2025
6265650
feat: adding Gluu's copyright and software license
duttarnab Feb 9, 2025
38e73ab
feat: adding android section in README
duttarnab Feb 10, 2025
c7a1ae9
feat: restoring python binding
duttarnab Feb 10, 2025
c981cd5
feat: update README and add fix to prevent WASM test failure
duttarnab Feb 11, 2025
63121bb
feat: correct typo in README
duttarnab Feb 11, 2025
00ad00d
feat: resolving review comments
duttarnab Feb 16, 2025
e3c4099
feat: resolving review comments
duttarnab Feb 16, 2025
d0e1f76
feat: adding uniffi binding docs
duttarnab Feb 16, 2025
b0d1f64
feat: adding uniffi binding docs
duttarnab Feb 16, 2025
de0997d
feat: adding missing files
duttarnab Feb 16, 2025
42b6747
feat: remove unused imports
duttarnab Feb 16, 2025
c52bb5c
feat: add demo video in docs
duttarnab Feb 16, 2025
6572058
feat: correct typo
duttarnab Feb 16, 2025
b61ed3f
fix: export uniffi::uniffi_bindgen_main
duttarnab Feb 17, 2025
b9b1556
fix: export uniffi::uniffi_bindgen_main
duttarnab Feb 17, 2025
deae330
fix: fixing wasm build error
duttarnab Feb 17, 2025
af9dfe3
fix: fixing wasm build error
duttarnab Feb 17, 2025
9966c04
feat: adding title to logs
duttarnab Feb 17, 2025
989d8ea
feat: resolving clippy error about missing function
duttarnab Feb 18, 2025
65cf3b0
feat: resolving clippy error about missing function
duttarnab Feb 18, 2025
0a6d218
feat: resolving clippy error about missing function
duttarnab Feb 18, 2025
7ea6a3b
Merge branch 'main' into jans-cedarling-issue-9432_2
duttarnab Feb 18, 2025
66d11b8
feat: resolving clippy error about empty line above main function
duttarnab Feb 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions docs/cedarling/uniffi/cedarling-ios.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Using UniFFI binding iOS App

Cedarling UniFFI binding exposes its `init`, `authz` and `log` interfaces to different languages and on all the different platforms, including Swift for iOS. This section covers how to build and use Cedarling UniFFI binding in an iOS app.

## Prerequisites

- Rust: Install it from [the official Rust website](https://www.rust-lang.org/tools/install).
- Xcode: Available on the Mac App Store.

## Building

1. Clone the jans monorepo and change directory to /path/of/jans/jans-cedarling

```
git clone https://github.com/JanssenProject/jans.git
cd /path/of/jans/jans-cedarling
```

1. Build the library:

```bash
cargo build
```

In target/debug, you should find the libmobile.dylib file.

2. Generate the bindings:

```bash
cargo run --bin uniffi-bindgen generate --library ./target/debug/libmobile.dylib --language swift --out-dir ./bindings/cedarling_uniffi/output
```

3. Building the iOS binaries and adding these targets to Rust.

```bash
rustup target add aarch64-apple-ios-sim aarch64-apple-ios
```

4. Build the library for Swift.

```bash
cargo build --release --target=aarch64-apple-ios-sim
cargo build --release --target=aarch64-apple-ios
```

You should have two binaries target/aarch64-apple-ios-sim/release/libmobile.a and target/aarch64-apple-ios/release/libmobile.a.

5. The XCFramework will allow us to import the library with zero effort in Xcode. First, we need to rename the file ./bindings/cedarling_uniffi/output/mobileFFI.modulemap to ./bindings/cedarling_uniffi/output/module.modulemap.

Then, we can create the XCFramework:

```bash
xcodebuild -create-xcframework \
-library ./target/aarch64-apple-ios-sim/release/libmobile.a -headers ./bindings/cedarling_uniffi/output \
-library ./target/aarch64-apple-ios/release/libmobile.a -headers ./bindings/cedarling_uniffi/output \
-output "ios/Mobile.xcframework"
```

6. Open ./jans-cedarling/bindings/cedarling_uniffi/iOSApp in Xcode. Import both the XCFramework Mobile.xcframework and the Swift file bindings bindings/output/mobile.swift files into your project (drag and drop should work).

7. Run iOS project on simulator.

We have included [a sample iOS app](https://github.com/JanssenProject/jans/tree/main/jans-cedarling/bindings/cedarling_uniffi/iOSApp) using Cedarling UniFFI binding for making authorisation decisions. Here is a demonstration video of its working.

<iframe src="https://www.loom.com/share/553e53a95a4a4e40ae54fc256538d7f9?sid=2e80f4bb-326d-4aa2-8d3b-f6abe62956db" allowfullscreen></iframe>
163 changes: 163 additions & 0 deletions docs/cedarling/uniffi/cedarling-uniffi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# UniFFI binding for Cedarling

[UniFFI](https://mozilla.github.io/uniffi-rs/latest/) (Universal Foreign Function Interface) is a tool developed by Mozilla to simplify cross-language bindings, primarily between Rust and other languages like Kotlin, Swift, and Python. It allows Rust libraries to be used in these languages without manually writing complex foreign function interface (FFI) bindings. For eg. developing iOS applications typically involves languages like Swift or Objective-C. However, with the advent of UniFFI, it’s now possible to use rust code iOS apps.

Speaking about Cedarling, it interacts with outside world mainly using 3 interfaces `init`, `authz` and `log`. The UniFFI binding for Cedarling wraps the init, authz and log interfaces of Cedarling and uses the [Procedural Macros](https://mozilla.github.io/uniffi-rs/latest/proc_macro/index.html) to expose them to other languages. It also exposes the required Structs and Enums used as parameters and return-types in these interfaces.

## Exposed Functions

1. **Cedarling::load_from_json**

Loads a Cedarling instance from a JSON configuration.

```declarative
#[uniffi::constructor]
pub fn load_from_json(config: String) -> Result<Self, CedarlingError>
```

**Usage in Swift:**

```declarative
let cedarling = try Cedarling.loadFromJson(config: jsonString)
```

2. **Cedarling::load_from_file**

Loads a Cedarling instance from a configuration file.

```declarative
#[uniffi::constructor]
pub fn load_from_file(path: String) -> Result<Self, CedarlingError>
```

**Usage in Swift:**

```declarative
let cedarling = try Cedarling.loadFromFile(path: "/path/to/config.json")

```

3. **Cedarling::authorize**

Handles authorization requests.

```declarative
#[uniffi::method]
pub fn authorize(
&self,
tokens: HashMap<String, String>,
action: String,
resource_type: String,
resource_id: String,
payload: String,
context: String,
) -> Result<AuthorizeResult, AuthorizeError>
```

**Usage in Swift:**

```declarative
let result = try cedarling.authorize(tokens: tokenMap, action: "read", resourceType: "file", resourceId: "123", payload: "{}", context: "")

```

4. **Cedarling::pop_logs**

Retrieves logs as JSON strings.

```declarative
#[uniffi::method]
pub fn pop_logs(&self) -> Result<Vec<String>, LogError>
```

**Usage in Swift:**

```declarative
let logs = try cedarling.popLogs()

```

5. **Cedarling::get_log_by_id**

Retrieves a log entry by ID.

```declarative
#[uniffi::method]
pub fn get_log_by_id(&self, id: &str) -> Result<String, LogError>
```

**Usage in Swift:**

```declarative
let log = try cedarling.getLogById(id: "log123")

```

6. **Cedarling::get_log_ids**

Get all log ids

```declarative
#[uniffi::method]
pub fn get_log_ids(&self) -> Vec<String>
```

**Usage in Swift:**

```declarative
let ids = try cedarling.getLogIds()

```

7. **Cedarling::get_logs_by_tag**

Get logs by tag, like `log_kind` or `log level`.

```declarative
#[uniffi::method]
pub fn get_logs_by_tag(&self, tag: &str) -> Result<Vec<String>, LogError> {

```

**Usage in Swift:**

```declarative
let logs = try cedarling.getLogsByTag(tag: "DEBUG")

```

8. **Cedarling::get_logs_by_request_id**

Get all logs by request_id

```declarative
#[uniffi::method]
pub fn get_logs_by_request_id(&self, request_id: &str) -> Result<Vec<String>, LogError>
```

**Usage in Swift:**

```declarative
let logs = try cedarling.getLogsByRequestId(request_id: "12434-32323-43434")

```

9. **Cedarling::get_logs_by_request_id_and_tag**

Get log by request_id and tag, like composite key `request_id` + `log_kind`.

```declarative
#[uniffi::method]
pub fn get_logs_by_request_id_and_tag(
&self,
request_id: &str,
tag: &str,
) -> Result<Vec<String>, LogError>
```

**Usage in Swift:**

```declarative
let logs = try cedarling.getLogsByRequestIdAndTag(request_id: "12434-32323-43434", tag: "Decision")

```
3 changes: 3 additions & 0 deletions jans-cedarling/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,6 @@ docs/_build/

# Pyenv
.python-version

# allow commit of cedarling_native_apps bindings
!/bindings/cedarling_uniffi/src/bin
24 changes: 24 additions & 0 deletions jans-cedarling/bindings/cedarling_uniffi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "cedarling_uniffi"
version = "0.1.0"
edition = "2021"

[lib]
crate_type = ["cdylib", "staticlib"]
name = "mobile"

# dependency for NOT wasm target
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
cedarling = { workspace = true, features = ["blocking"]}
jsonwebtoken = "9.3.0"
openssl = { version = "0.10.35", features = ["vendored"] }
once_cell = "1.20.2"
uniffi = { version = "0.29.0", features = [ "cli" ] }
uniffi_macros = "0.29.0" # Procedural macros support
serde = { workspace = true }
serde_json = { workspace = true }
thiserror.workspace = true

[dev-dependencies]
# is used in testing
test_utils = { workspace = true }
62 changes: 62 additions & 0 deletions jans-cedarling/bindings/cedarling_uniffi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Cedarling UniFFI binding

This module is designed to build Cedarling UniFFI binding for iOS and android apps.

## iOS

Read [this article](https://medium.com/@arnab.bdutta/janssen-cedarling-uniffi-bindings-for-native-apps-90f36982c894) for details.

### Prerequisites

- Rust: Install it from [the official Rust website](https://www.rust-lang.org/tools/install).
- Xcode: Available on the Mac App Store.

### Building

1. Build the library:

```bash
cargo build
```

In target/debug, you should find the libmobile.dylib file.

2. Generate the bindings:

```bash
cargo run --bin uniffi-bindgen generate --library ./target/debug/libmobile.dylib --language swift --out-dir ./bindings/cedarling_uniffi/output
```

3. Building the iOS binaries and adding these targets to Rust.

```bash
rustup target add aarch64-apple-ios-sim aarch64-apple-ios
```

4. Build the library for Swift.

```bash
cargo build --release --target=aarch64-apple-ios-sim
cargo build --release --target=aarch64-apple-ios
```

You should have two binaries target/aarch64-apple-ios-sim/release/libmobile.a and target/aarch64-apple-ios/release/libmobile.a.

5. The XCFramework will allow us to import the library with zero effort in Xcode. First, we need to rename the file ./bindings/cedarling_uniffi/output/mobileFFI.modulemap to ./bindings/cedarling_uniffi/output/module.modulemap.

Then, we can create the XCFramework:

```bash
xcodebuild -create-xcframework \
-library ./target/aarch64-apple-ios-sim/release/libmobile.a -headers ./bindings/cedarling_uniffi/output \
-library ./target/aarch64-apple-ios/release/libmobile.a -headers ./bindings/cedarling_uniffi/output \
-output "ios/Mobile.xcframework"
```

6. Open ./jans-cedarling/bindings/cedarling_uniffi/iOSApp in Xcode. Import both the XCFramework Mobile.xcframework and the Swift file bindings bindings/output/mobile.swift files into your project (drag and drop should work).

7. Run iOS project on simulator.

## Android

- WIP
62 changes: 62 additions & 0 deletions jans-cedarling/bindings/cedarling_uniffi/iOSApp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore

## User settings
xcuserdata/

## Obj-C/Swift specific
*.hmap

## App packaging
*.ipa
*.dSYM.zip
*.dSYM

## Playgrounds
timeline.xctimeline
playground.xcworkspace

# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
# Package.pins
# Package.resolved
# *.xcodeproj
#
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
# hence it is not needed unless you have added a package configuration file to your project
# .swiftpm

.build/

# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
#
# Add this line if you want to avoid checking in source code from the Xcode workspace
# *.xcworkspace

# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts

Carthage/Build/

# fastlane
#
# It is recommended to not store the screenshots in the git repo.
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/#source-control

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
Loading
Loading