Skip to content
1Claw Academy
Curriculum/Advanced Security3 minAdvanced · Lesson 11 of 11

Lab: check what a real federated token would need to pass

Lab

Use 1Claw's real issuer and real JWKS to write the audience check the federation lesson described, against the actual production values rather than invented ones.

The security-foundations JWKS lab showed you two real keys. This lab uses them for something: writing the exact verification a relying party would run on a 1Claw federation token, against the real issuer this course has been citing throughout.

  1. 1

    Confirm the real values this check depends on.

    code
    curl -s https://api.1claw.co/.well-known/openid-configuration | python3 -c '
    import json, sys
    d = json.load(sys.stdin)
    print("issuer:  ", d["issuer"])
    print("jwks_uri:", d["jwks_uri"])
    '
  2. 2

    Both match what every lesson in this course has assumed without you checking.

    text
    issuer:   https://api.1claw.co
    jwks_uri: https://api.1claw.co/.well-known/jwks.json
  3. 3

    Write the check a relying party actually runs: does a token's iss match this issuer, and does its aud match this service. Use a token shaped like a real federated one, since 1Claw will not hand you a live signed one without an account.

    code
    python3 -c '
    import json
    
    ISSUER = "https://api.1claw.co"  # confirmed live above
    
    def verify(token_claims, expected_audience):
        if token_claims["iss"] != ISSUER:
            return "REJECT: iss is " + token_claims["iss"] + ", not " + ISSUER
        if token_claims["aud"] != expected_audience:
            return "REJECT: aud is " + token_claims["aud"] + ", not " + expected_audience
        return "ACCEPT"
    
    # a token genuinely issued by 1Claw, for a different service
    real_but_wrong_audience = {"iss": ISSUER, "aud": "https://billing.example.com"}
    
    # a token that merely claims to be from 1Claw
    forged_issuer = {"iss": "https://api.1claw.io", "aud": "https://deploy.example.com"}
    
    print(verify(real_but_wrong_audience, "https://deploy.example.com"))
    print(verify(forged_issuer, "https://deploy.example.com"))
    '
  4. 4

    Both rejected, for different reasons, against the real issuer this course has cited every time.

    text
    REJECT: aud is https://billing.example.com, not https://deploy.example.com
    REJECT: iss is https://api.1claw.io, not https://api.1claw.co

The second rejection is the one worth reading twice. api.1claw.io is not api.1claw.co, and it is exactly the kind of difference an inattentive check misses. Hardcoding the real issuer, confirmed live rather than copied from a lesson, is what makes that check meaningful rather than decorative.

  • This is the read-a-jwt lab's replay attack, run against 1Claw's actual issuer value instead of a placeholder. The mechanism does not change; using the real value is what makes it a check on the real system rather than a story about one.
  • The federation lesson's RFC 8693 token exchange exists to produce exactly the audience-bound token this check is written for. The exchange sets aud to whatever the relying party requested, so the relying party validating it is closing the loop it opened.
  • You cannot get a real, live, validly-signed federation token here without an account and an enabled agent. What you can do, and just did, is confirm the two facts, issuer and key location, that a correct implementation depends on getting right.
Watch out

federation_audiences on the agent side is an allowlist of what a token may be requested for. This check is the other half, on the relying party's side: verifying that what arrived matches what you specifically asked for. Both halves are required; either alone is incomplete.

Tip

If you build a relying party for federated 1Claw tokens, do not hardcode the issuer string into your code from a lesson you read once. Fetch it from the discovery document at startup, the way this lab just did, so a future change is picked up rather than silently mismatched.

Check your understanding

3 questions
1

Why does the check reject a token with iss set to api.1claw.io?

2

Why is a token with a correct issuer but the wrong audience still rejected?

3

Why fetch the issuer from the discovery document at runtime instead of hardcoding it from a lesson?