{"id":21866951,"url":"https://github.com/nitram509/jmacaroons","last_synced_at":"2025-07-22T23:02:31.127Z","repository":{"id":19828267,"uuid":"23089367","full_name":"nitram509/jmacaroons","owner":"nitram509","description":"Pure Java implementation of Macaroons: Cookies with Contextual Caveats for Decentralized Authorization in the Cloud. Android ready. Online playground available. Project is STALE","archived":false,"fork":false,"pushed_at":"2024-12-09T04:38:09.000Z","size":1521,"stargazers_count":117,"open_issues_count":4,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-24T15:20:01.836Z","etag":null,"topics":["authentication","crypto","crypto-library","cryptography","cryptography-library","java-library","macaroons"],"latest_commit_sha":null,"homepage":"https://macaroons.io/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nitram509.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-08-18T23:00:53.000Z","updated_at":"2024-11-15T13:20:02.000Z","dependencies_parsed_at":"2024-12-25T13:09:45.060Z","dependency_job_id":"8bb9361f-4d28-4839-b3ae-92ba15cd4156","html_url":"https://github.com/nitram509/jmacaroons","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/nitram509/jmacaroons","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitram509%2Fjmacaroons","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitram509%2Fjmacaroons/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitram509%2Fjmacaroons/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitram509%2Fjmacaroons/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nitram509","download_url":"https://codeload.github.com/nitram509/jmacaroons/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nitram509%2Fjmacaroons/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266586839,"owners_count":23952199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","crypto","crypto-library","cryptography","cryptography-library","java-library","macaroons"],"created_at":"2024-11-28T05:07:59.782Z","updated_at":"2025-07-22T23:02:31.099Z","avatar_url":"https://github.com/nitram509.png","language":"Java","readme":"Macaroons are Better Than Cookies!\n==================================\n\nThis Java library provides an implementation of macaroons[[1]](http://research.google.com/pubs/pub41892.html),\nwhich are flexible authorization tokens that work great in distributed systems.\nLike cookies, macaroons are bearer tokens that enable applications to ascertain whether their\nholders' actions are authorized.  But macaroons are better than cookies!\n\nThis project started as a port of libmacaroons[[2]](https://github.com/rescrv/libmacaroons) library.\nThe primary goals are\n   * being compatible to libmacaroons\n   * having no external dependencies, except the Java Runtime\n   * being very much backward compatible, while using Java8\n   * focus on binary serialization format (currently, JSON format isn't supported)\n   * being the reference implementation in the Java community ;-)\n\nThere is a [playground](http://www.macaroons.io/) (testing environment) available,\nwhere you can build and verify macaroons online.\n\n##### License\n\n[![License](https://img.shields.io/:license-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n\nUsage/Import In Your Project\n----------------------------------\n\nThis library jmacaroons is available via Maven Central.\nRequires Java 1.11+\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.nitram509/jmacaroons.svg)](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.github.nitram509%22%20AND%20a%3A%22jmacaroons%22)\n\n\nMaven\n````xml\n\u003cdependency\u003e\n  \u003cgroupId\u003ecom.github.nitram509\u003c/groupId\u003e\n  \u003cartifactId\u003ejmacaroons\u003c/artifactId\u003e\n  \u003cversion\u003e0.5.0\u003c/version\u003e\n\u003c/dependency\u003e\n````\n\nGradle\n````groovy\ncompile 'com.github.nitram509:jmacaroons:0.5.0'\n````\n\n\nBuild Status\n--------------------\n\n[![maven test](https://github.com/nitram509/jmacaroons/actions/workflows/maven-test.yml/badge.svg)](https://github.com/nitram509/jmacaroons/actions/workflows/maven-test.yml)\n\n[![codecov](https://codecov.io/gh/nitram509/jmacaroons/branch/master/graph/badge.svg?token=G4BT0ayhLV)](https://codecov.io/gh/nitram509/jmacaroons)\n\nCommunity \u0026 Badges\n--------------------\n\nListed on Android Arsenal: [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-jmacaroons-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/914)\n\n\nCreating Your First Macaroon\n----------------------------------\n\nLets create a simple macaroon\nOf course, this macaroon can be displayed in a more human-readable form\nfor easy debugging\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=37-47) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  Macaroon create() {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n    Macaroon macaroon = Macaroon.create(location, secretKey, identifier);\n    System.out.println(macaroon.inspect());\n    // \u003e location http://www.example.org\n    // \u003e identifier we used our secret key\n    // \u003e signature e3d9e02908526c4c0039ae15114115d97fdd68bf2ba379b342aaf0f617d0552f\n    return macaroon;\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\nSerializing\n----------------------------------\n\nMacaroons are serialized, using Base64 URL safe encoding [RFC 4648](http://www.ietf.org/rfc/rfc4648.txt).\nThis way you can very easily append it to query string within URIs.\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=49-54) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void serialize() {\n    Macaroon macaroon = create();\n    String serialized = macaroon.serialize();\n    System.out.println(\"Serialized: \" + serialized);\n    // Serialized: MDAyNGxvY2F0aW9uIGh0dHA6Ly93d3cuZXhhbXBsZS5vcmcKMDAyNmlkZW50aWZpZXIgd2UgdXNlZCBvdXIgc2VjcmV0IGtleQowMDJmc2lnbmF0dXJlIOPZ4CkIUmxMADmuFRFBFdl_3Wi_K6N5s0Kq8PYX0FUvCg\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nAlternatively, the V2 binary serializer format is supported.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=216-221) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void serialize_v2_binary_format() {\n    Macaroon macaroon = create();\n    String serialized = macaroon.serialize(V2);\n    System.out.println(\"Serialized: \" + serialized);\n    // Serialized: AgEWaHR0cDovL3d3dy5leGFtcGxlLm9yZwIWd2UgdXNlZCBvdXIgc2VjcmV0IGtleQAABiDj2eApCFJsTAA5rhURQRXZf91ovyujebNCqvD2F9BVLw\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\n_Note:_\nBase64 URL safe is supported since v0.3.0. jmacaroons also de-serializes regular Base64 to maintain backward compatibility.\n\n\nDe-Serializing\n----------------------------------\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=56-63) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void deserialize() {\n    String serialized = create().serialize();\n    Macaroon macaroon = Macaroon.deserialize(serialized);\n    System.out.println(macaroon.inspect());\n    // \u003e location http://www.example.org\n    // \u003e identifier we used our secret key\n    // \u003e signature e3d9e02908526c4c0039ae15114115d97fdd68bf2ba379b342aaf0f617d0552f\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\nVerifying Your Macaroon\n----------------------------------\n\nA verifier can only ever successfully verify a macaroon\nwhen provided with the macaroon and its corresponding secret - no secret, no authorization.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=65-71) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void verify() throws InvalidKeyException, NoSuchAlgorithmException {\n    Macaroon macaroon = create();\n    MacaroonsVerifier verifier = new MacaroonsVerifier(macaroon);\n    String secret = \"this is our super secret key; only we should know it\";\n    boolean valid = verifier.isValid(secret);\n    // \u003e True\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\nAdding Caveats\n-----------------------------------\n\nWhen creating a new macaroon, you can add a caveat to our macaroon that\nrestricts it to just the account number 3735928559.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=73-81) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void addCaveat() throws InvalidKeyException, NoSuchAlgorithmException {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n    Macaroon macaroon = Macaroon.builder(location, secretKey, identifier)\n        .addCaveat(\"account = 3735928559\")\n        .build();\n    System.out.println(macaroon.inspect());\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nBecause macaroon objects are immutable, they have to be modified\nvia ```Macaroon.builder()```. Thus, a new macaroon object will be created.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=83-93) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void addCaveat_modify() throws InvalidKeyException, NoSuchAlgorithmException {\n    Macaroon macaroon = create();\n    macaroon = Macaroon.builder(macaroon)\n        .addCaveat(\"account = 3735928559\")\n        .build();\n    System.out.println(macaroon.inspect());\n    // \u003e location http://www.example.org\n    // \u003e identifier we used our secret key\n    // \u003e cid account = 3735928559\n    // \u003e signature 1efe4763f290dbce0c1d08477367e11f4eee456a64933cf662d79772dbb82128\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\nVerifying Macaroons With Caveats\n--------------------------------\n\nThe verifier should say that this macaroon is unauthorized because\nthe verifier cannot prove that the caveat (account = 3735928559) is satisfied.\nWe can see that it fails just as we would expect.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=95-104) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void verify_required_caveats() throws InvalidKeyException, NoSuchAlgorithmException {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n    Macaroon macaroon = Macaroon.builder(location, secretKey, identifier)\n        .addCaveat(\"account = 3735928559\")\n        .build();\n    MacaroonsVerifier verifier = new MacaroonsVerifier(macaroon);\n    verifier.isValid(secretKey);\n    // \u003e False\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nCaveats like these are called \"exact caveats\" because there is exactly one way\nto satisfy them.  Either the account number is 3735928559, or it isn't.  At\nverification time, the verifier will check each caveat in the macaroon against\nthe list of satisfied caveats provided to \"satisfyExact()\".  When it finds a\nmatch, it knows that the caveat holds and it can move onto the next caveat in\nthe macaroon.\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=106-108) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    verifier.satisfyExact(\"account = 3735928559\");\n    verifier.isValid(secretKey);\n    // \u003e True\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nThe verifier can be made more general, and be \"future-proofed\",\nso that it will still function correctly even if somehow the authorization\npolicy changes; for example, by adding the three following facts,\nthe verifier will continue to work even if someone decides to\nself-attenuate itself macaroons to be only usable from IP address and browser:\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=110-115) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    verifier.satisfyExact(\"IP = 127.0.0.1')\");\n    verifier.satisfyExact(\"browser = Chrome')\");\n    verifier.satisfyExact(\"action = deposit\");\n    verifier.isValid(secretKey);\n    // \u003e True\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nThere is also a more general way to check caveats, via callbacks.\nWhen providing such a callback to the verifier,\nit is able to check if the caveat satisfies special constrains. \n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=117-132) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void verify_general_caveats() throws InvalidKeyException, NoSuchAlgorithmException {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n\n    Macaroon macaroon = Macaroon.builder(location, secretKey, identifier)\n        .addCaveat(\"time \u003c 2042-01-01T00:00\")\n        .build();\n    MacaroonsVerifier verifier = new MacaroonsVerifier(macaroon);\n    verifier.isValid(secretKey);\n    // \u003e False\n\n    verifier.satisfyGeneral(new TimestampCaveatVerifier());\n    verifier.isValid(secretKey);\n    // \u003e True\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n    \n\nThird Party Caveats\n---------------------\n\nLike first-party caveats, third-party caveats restrict the context in which a\nmacaroon is authorized, but with a different form of restriction.  Where a\nfirst-party caveat is checked directly within the verifier, a third-party caveat\nis checked by the third-party, who provides a discharge macaroon to prove that\nthe original third-party caveat is true.  The discharge macaroon is recursively\ninspected by the verifier; if it verifies successfully, the discharge macaroon\nserves as a proof that the original third-party caveat is satisfied.  Of course,\nnothing stops discharge macaroons from containing embedded first- or third-party\ncaveats for the verifier to consider during verification.\n\nLet's rework the above example to provide Alice with access to her account only\nafter she authenticates with a service that is separate from the service\nprocessing her banking transactions.\n\nAs before, we'll start by constructing a new macaroon with the caveat that is\nlimited to Alice's bank account.\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=134-159) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void with_3rd_party_caveats() {\n    // create a simple macaroon first\n    String location = \"http://mybank/\";\n    String secret = \"this is a different super-secret key; never use the same secret twice\";\n    String publicIdentifier = \"we used our other secret key\";\n    MacaroonsBuilder mb = Macaroon.builder(location, secret, publicIdentifier)\n        .addCaveat(\"account = 3735928559\");\n\n    // add a 3rd party caveat\n    // you'll likely want to use a higher entropy source to generate this key\n    String caveat_key = \"4; guaranteed random by a fair toss of the dice\";\n    String predicate = \"user = Alice\";\n    // send_to_3rd_party_location_and_do_auth(caveat_key, predicate);\n    // identifier = recv_from_auth();\n    String identifier = \"this was how we remind auth of key/pred\";\n    Macaroon m = mb.addCaveat(\"http://auth.mybank/\", caveat_key, identifier)\n        .build();\n\n    System.out.println(m.inspect());\n    // \u003e location http://mybank/\n    // \u003e identifier we used our other secret key\n    // \u003e cid account = 3735928559\n    // \u003e cid this was how we remind auth of key/pred\n    // \u003e vid AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA027FAuBYhtHwJ58FX6UlVNFtFsGxQHS7uD_w_dedwv4Jjw7UorCREw5rXbRqIKhr\n    // \u003e cl http://auth.mybank/\n    // \u003e signature d27db2fd1f22760e4c3dae8137e2d8fc1df6c0741c18aed4b97256bf78d1f55c\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nIn a real application, we'd look at these third party caveats, and contact each\nlocation to retrieve the requisite discharge macaroons. We would include the\nidentifier for the caveat in the request itself, so that the server can recall\nthe secret used to create the third-party caveat. The server can then generate\nand return a new macaroon that discharges the caveat:\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=161-167) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    final String oneHourFromNow = Instant.now()\n        .plus(Duration.ofHours(1))\n        .toString();\n\n    Macaroon d = Macaroon.builder(\"http://auth.mybank/\", caveat_key, identifier)\n        .addCaveat(\"time \u003c \" + oneHourFromNow)\n        .build();\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nThis new macaroon enables the verifier to determine that the third party caveat\nis satisfied. Our target service added a time-limiting caveat to this macaroon\nthat ensures that this discharge macaroon does not last forever.  This ensures\nthat Alice (or, at least someone authenticated as Alice) cannot use the\ndischarge macaroon indefinitely and will eventually have to re-authenticate.\n\nOnce Alice has both the root macaroon and the discharge macaroon in her\npossession, she can make the request to the target service. Making a request\nwith discharge macaroons is only slightly more complicated than making requests\nwith a single macaroon. In addition to serializing and transmitting all\ninvolved macaroons, there is preparation step that binds the discharge macaroons\nto the root macaroon. This binding step ensures that the discharge macaroon is\nuseful only when presented alongside the root macaroon. The root macaroon is\nused to bind the discharge macaroons like this:\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=169-171) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    Macaroon dp = Macaroon.builder(m)\n        .prepareForRequest(d)\n        .build();\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nIf we were to look at the signatures on these prepared discharge macaroons, we\nwould see that the binding process has irreversibly altered their signature(s).\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=173-176) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    System.out.println(\"d.signature = \" + d.signature);\n    System.out.println(\"dp.signature = \" + dp.signature);\n    // \u003e d.signature = 82a80681f9f32d419af12f6a71787a1bac3ab199df934ed950ddf20c25ac8c65\n    // \u003e dp.signature = 2eb01d0dd2b4475330739140188648cf25dda0425ea9f661f1574ca0a9eac54e\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nThe root macaroon 'm' and its discharge macaroons 'dp' are ready for the\nrequest.  Alice can serialize them all and send them to the bank to prove she is\nauthorized to access her account. The bank can verify them using the same\nverifier we built before.  We provide the discharge macaroons as a third\nargument to the verify call:\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=178-184) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n    new MacaroonsVerifier(m)\n        .satisfyExact(\"account = 3735928559\")\n        .satisfyGeneral(new TimestampCaveatVerifier())\n        .satisfy3rdParty(dp)\n        .assertIsValid(secret);\n    // \u003e ok.\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\nWithout the 'prepare_for_request()' call, the verification would fail.\n\n\nCommonly used verifier, shipped with jmacaroons\n--------------------------------------------------\n\n##### Time to live verification\n\nApplying a timestamp in the future to a macaroon will provide time to live semantics.\nGiven that all machines have synchronized clocks, a general macaroon verifier is able to check\nfor expiration.\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=186-199) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void timestamp_verifier() {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n\n    Macaroon macaroon = Macaroon.builder(location, secretKey, identifier)\n        .addCaveat(\"time \u003c 2015-01-01T00:00\")\n        .build();\n\n    new MacaroonsVerifier(macaroon)\n        .satisfyGeneral(new TimestampCaveatVerifier())\n        .isValid(secretKey);\n    // \u003e True\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n##### Authorities verification\n\nMacaroons may also embed authorities. Thus a general macaroon verifier is able\nto check for a single authority.\n\n\u003c!-- MARKDOWN-AUTO-DOCS:START (CODE:src=./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java\u0026lines=201-214) --\u003e\n\u003c!-- The below code snippet is automatically added from ./src/example/java/com/github/nitram509/jmacaroons/examples/MacaroonsExamples.java --\u003e\n```java\n  void authorities_verifier() {\n    String location = \"http://www.example.org\";\n    String secretKey = \"this is our super secret key; only we should know it\";\n    String identifier = \"we used our secret key\";\n\n    Macaroon macaroon = Macaroon.builder(location, secretKey, identifier)\n        .addCaveat(\"authorities = ROLE_USER, DEV_TOOLS_AVAILABLE\")\n        .build();\n\n    new MacaroonsVerifier(macaroon)\n        .satisfyGeneral(hasAuthority(\"DEV_TOOLS_AVAILABLE\"))\n        .isValid(secretKey);\n    // \u003e True\n  }\n```\n\u003c!-- MARKDOWN-AUTO-DOCS:END --\u003e\n\n\nChoosing Secrets\n-------------------\n\nFor clarity, we've generated human-readable secrets that we use as the root keys\nof all of our macaroons.  In practice, this is terribly insecure and can lead to\nmacaroons that can easily be forged because the secret is too predictable.  To\navoid this, we recommend generating secrets using a sufficient number of\nsuitably random bytes.  Because the bytes are a secret key, they should be drawn\nfrom a source with enough entropy to ensure that the key cannot be guessed\nbefore the macaroon falls out of use.\n\nThe jmacaroons library exposes a constant that is the ideal number of bytes these\nsecret keys should contain.  Any shorter is wasting an opportunity for security.\n\n````java\ncom.github.nitram509.jmacaroons.MacaroonsConstants.MACAROON_SUGGESTED_SECRET_LENGTH = 32\n````\n\n\nPerformance\n--------------\n\nThere's a little micro benchmark, which demonstrates the performance of jmacaroons.\n\nSource: https://gist.github.com/nitram509/b6f836a697b405e5f440\n\nEnvironment: Windows 8.1 64bit, JRE 1.8.0_25 64bit, Intel i7-4790 @3.60GHz\n\n````text\nResults\n----------\nBenchmark                                                                    Mode  Samples        Score       Error  Units\no.s.JMacaroonsBenchmark.benchmark_Deserialize                               thrpt        5  2190474,677 ± 44591,197  ops/s\no.s.JMacaroonsBenchmark.benchmark_Deserialize_and_Verify_key_bytes          thrpt        5   457262,262 ±  5868,723  ops/s\no.s.JMacaroonsBenchmark.benchmark_Deserialize_and_Verify_key_string         thrpt        5   262689,398 ±  4270,857  ops/s\no.s.JMacaroonsBenchmark.benchmark_Serialize_with_key_bytes                  thrpt        5   424008,024 ± 16222,450  ops/s\no.s.JMacaroonsBenchmark.benchmark_Serialize_with_key_bytes_and_1_caveat     thrpt        5   242060,835 ±  5696,272  ops/s\no.s.JMacaroonsBenchmark.benchmark_Serialize_with_key_bytes_and_2_caveats    thrpt        5   166017,277 ±   870,467  ops/s\no.s.JMacaroonsBenchmark.benchmark_Serialize_with_key_bytes_and_3_caveats    thrpt        5   127712,773 ±   478,394  ops/s\no.s.JMacaroonsBenchmark.benchmark_Serialize_with_key_string                 thrpt        5   252302,839 ±  3277,232  ops/s\n````\n\n\n## Stargazers over time\n\n[![Stargazers over time](https://starchart.cc/nitram509/jmacaroons.svg)](https://starchart.cc/nitram509/jmacaroons)\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitram509%2Fjmacaroons","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnitram509%2Fjmacaroons","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnitram509%2Fjmacaroons/lists"}