diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 96d322b..85a3380 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -20,6 +20,7 @@ - [NodeJS](usage/nodejs.md) - [Python](usage/python.md) - [Rust](usage/rust.md) + - [Swift](usage/swift.md) - [Web components](usage/web-components.md) ## Recipes diff --git a/docs/src/usage.md b/docs/src/usage.md index 9c94182..9284230 100644 --- a/docs/src/usage.md +++ b/docs/src/usage.md @@ -8,4 +8,5 @@ - [NodeJS](./usage/nodejs.md) - [Python](./usage/python.md) - [Rust](./usage/rust.md) +- [Swift](./usage/swift.md) - [Web components](./usage/web-components.md) diff --git a/docs/src/usage/python.md b/docs/src/usage/python.md index 4e21efd..9351e40 100644 --- a/docs/src/usage/python.md +++ b/docs/src/usage/python.md @@ -2,4 +2,4 @@ Python bindings for Biscuit are distributed on [PyPI](https://pypi.org/project/biscuit-python). They wrap the [Biscuit Rust library](https://github.com/eclipse-biscuit/biscuit-rust), and provide a pythonic API. -Detailed documentation is available at . \ No newline at end of file +Detailed documentation is available at . diff --git a/docs/src/usage/swift.md b/docs/src/usage/swift.md new file mode 100644 index 0000000..ff3e3f2 --- /dev/null +++ b/docs/src/usage/swift.md @@ -0,0 +1,94 @@ +# Swift + +See . + +## Tutorial + +The central type of the Biscuits library is the `Biscuit` type, which represents a biscuit token. +Such tokens can be constructed, attenuated, authorized, serialized, deserialized and so on. + +The library exposes protocols for valid public and private keys; these protocols are implemented by +the `Curve25519`, `P256` and `SecureEnclave.P256` types from [swift-crypto][swift-crypto]; users may +also add implementations for alternative implementations of ed25519 and secp256r1 if they desire. + +The Datalog contents of a biscuit token can be encoded in two ways: either as a string, which will be +parsed at runtime, or using a DSL provided by the library which is type safe and avoids the risk +of injection attacks and syntax errors. + +For example: + +```swift +import Biscuits +import Crypto +import Foundation + +let issuerPrivateKey = Curve25519.Signing.PrivateKey() +// Or, if secp256r1 is more your style... +// let issuerPrivateKey = P256.Signing.PrivateKey() + +// Construct a biscuit for a user with specific userID: +let userToken = try Biscuit(rootKey: issuerPrivateKey) { + Check.checkIf { + Predicate("user", userID) + } + // This is a convenience for defining an expiration check based on the time fact: + Check.tokenExpires(at: expirationDate) +} +``` + +In addition to using that biscuit as a bearer token themselves, that user would be able to attenuate +it to give a third party service read-only access to resources under the `/foo` directory: + +```swift +let readOnlyFooToken = try userToken.attenuated() { + // equivalent to: check if operation("read"), resource($path), $path.starts_with("/foo"); + Check.checkIf { + Predicate("operation", "read") + Predicate("resource", Term(variable: "path")) + Term(variable: "path").startsWith("/foo") + } +} +``` + +Finally, the relying party could authorize a request to access the source at "/foo/bar" as that user +using an authorizer like this: + +```swift +try readOnlyFooToken.authorize() { + Fact("user", userID) + Fact("operation", "read") + Fact("resource", "/foo/bar") + Fact("time", Date.now) +} +``` + +### Datalog DSL + +The Datalog DSL has two [resultBuilder][resultBuilder]-based entry points: `DatalogBlock` and +`Authorizer`. `DatalogBlock` is used for constructing and attenuating biscuits, whereas `Authorizer` +is used for authorizing them. + +Each contain a series of datalog statements of these types: `Fact`, `Rule`, `Check`, and, in the +case of `Authorizer`, `Policy`. Facts are simple statements, consisting of the name of that fact and +a series of values passed to that fact. Rules, checks, and policies are compound statements +consisting of a series of predicates and expressions. + +A `Predicate` is similar to `Fact`, but it can also take variables (which are written +`Term(variable: "name")`), not only literal values. When authorizing the biscuit, these predicates +will be supported by finding facts that match their name and values. + +Expressions can be built using a fluent method-based expression builder API, supported on +`Expression`, `Value` and `Term`. For example: + +```swift +// equivalent to $foo +let foo = Term(variable: "foo") +// $foo > 0 && $foo < 100 +foo.greaterThan(0).and(foo.lessThan(100)) +``` +## API reference + +API reference is available at . + +[swift-crypto]: https://github.com/apple/swift-crypto +[resultBuilder]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/advancedoperators/#Result-Builders