Skip to content

Commit

Permalink
Add backend to verify delegates.
Browse files Browse the repository at this point in the history
  • Loading branch information
q-uint committed Jul 2, 2024
1 parent c5a5b96 commit 576183b
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 15 deletions.
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# Internet Identity Auth Flow w/ Golang

This is a simple example of how to authenticate with the Internet Identity using Golang.

## How to Run

### Backend

```shell
go run main.go
```

### Frontend

```shell
parcel src/index.html
```
9 changes: 9 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
module github.com/aviate-labs/ii-auth-go

go 1.22.3

require github.com/aviate-labs/agent-go v0.5.0

require (
github.com/aviate-labs/leb128 v0.3.0 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/herumi/bls-go-binary v1.34.0 // indirect
github.com/x448/float16 v0.8.4 // indirect
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/aviate-labs/agent-go v0.5.0 h1:qJpCBqRPIOgtCGgTYh0N2QH0v4hjFYu9SYJzz+4YDxU=
github.com/aviate-labs/agent-go v0.5.0/go.mod h1:GDXxQeob0bBy5Vfb4bnAfJR22S/sj4ApHpDUtg1LZtE=
github.com/aviate-labs/leb128 v0.3.0 h1:s9htRv3OYk8nuHqJu9PiVFJxv1jIUTIcpEeiURa91uQ=
github.com/aviate-labs/leb128 v0.3.0/go.mod h1:GclhBOjhIKmcDlgHKhj0AEZollzERfZUbcRUKiQVqgY=
github.com/aviate-labs/secp256k1 v0.0.0-5e6736a h1:aQkG/D+l8Y7tr809l8pN+KebH2jzacWReSFQmeEKFgM=
github.com/aviate-labs/secp256k1 v0.0.0-5e6736a/go.mod h1:C/lr3F9TimrVkdZckG5mz+VU0TrmpeyVKUjzv2YyGwA=
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/herumi/bls-go-binary v1.34.0 h1:x1sKp8zzx+alvlifB+vbA0KkY0Pz4Br31cZ/saDkiFE=
github.com/herumi/bls-go-binary v1.34.0/go.mod h1:O4Vp1AfR4raRGwFeQpr9X/PQtncEicMoOe6BQt1oX0Y=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
44 changes: 33 additions & 11 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ package main
import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"encoding/json"
"net/http"
"time"

"github.com/aviate-labs/agent-go/certification"
ii "github.com/aviate-labs/agent-go/certification/ii"
"github.com/aviate-labs/agent-go/ic"
"github.com/aviate-labs/agent-go/principal"
)

var challenge [32]byte
Expand Down Expand Up @@ -50,23 +57,38 @@ func main() {
var m struct {
Challenge string `json:"challenge"`
Delegation struct {
Kind string `json:"kind"`
Delegations []struct {
Delegation struct {
PubKey string `json:"pubkey"`
Expiration string `json:"expiration"`
}
Signature string `json:"signature"`
} `json:"delegations"`
UserPublicKey string `json:"userPublicKey"`
AuthnMethod string `json:"authnMethod"`
Kind string `json:"kind"`
Delegations []ii.SignedDelegation `json:"delegations"`
UserPublicKey ii.HexString `json:"userPublicKey"`
AuthnMethod string `json:"authnMethod"`
} `json:"delegation"`
}
if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
_ = m // TODO:validate delegation and signature
dc := ii.DelegationChain{
Delegations: m.Delegation.Delegations,
PublicKey: m.Delegation.UserPublicKey,
}
rawChallenge, _ := base64.StdEncoding.DecodeString(m.Challenge)
rootKey, _ := hex.DecodeString(certification.RootKey)
if err := dc.VerifyChallenge(
rawChallenge,
uint64(time.Now().UnixNano()),
ic.IDENTITY_PRINCIPAL,
rootKey,
); err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
}
payload, err := json.Marshal(map[string]any{
"principal": principal.NewSelfAuthenticating([]byte(m.Delegation.UserPublicKey)).String(),
})
if err != nil {
http.Error(w, "Internal error", http.StatusInternalServerError)
return
}
_, _ = w.Write(payload)
})
_ = http.ListenAndServe(":8123", nil)
}
29 changes: 28 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,37 @@
<html>
<head>
<title>Login w/ II</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:[email protected]&display=swap" rel="stylesheet">
<style>
* {
font-family: "Space Grotesk", sans-serif;
}

button {
padding: 10px 20px;
font-size: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
}

#root {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
</style>
</head>
<body>
<div id="root">
<button id="login">Login w/ II</button>
<button id="login">Login w/ Internet Identity</button>
<p id="principal"></p>
<hr/>
<button id="debug-login">DEBUG Login</button>
</div>
<script type="module" src="./index.ts"></script>
</body>
Expand Down
32 changes: 29 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {AuthClient} from "@dfinity/auth-client";

interface AuthReadyMessage {
kind: "authorize-ready";
}
Expand All @@ -18,8 +20,6 @@ interface AuthResponseSuccess {
async function login(
sessionPublicKey: Uint8Array,
): Promise<AuthResponseSuccess> {
console.log(sessionPublicKey);

const u = new URL("https://identity.ic0.app/");
u.hash = "#authorize";
const popup = window.open(u, "ii-window", "width=400,height=400");
Expand Down Expand Up @@ -62,13 +62,34 @@ async function login(
} else {
console.log("Received authorize message.")
popup.close();
console.log(authorizeMessageData);
return authorizeMessageData;
}
}
}

window.onload = async () => {
const debugLoginButton = document.getElementById("debug-login")!;
debugLoginButton.addEventListener("click", async () => {
const client = await AuthClient.create();
if (!await client.isAuthenticated()) {
await client.login({
identityProvider: "https://identity.ic0.app",
onSuccess: async () => {
console.log("Logged in!");
const identity = await client.getIdentity();
const principal = identity.getPrincipal();
console.log("Principal", principal.toText());
},
onError: (err) => {
console.error("Error logging in", err);
},
});
}
const identity = await client.getIdentity();
const principal = identity.getPrincipal();
console.log("Principal", principal.toText());
})

const loginButton = document.getElementById("login")!;
loginButton.addEventListener("click", async () => {
const challengeResp = await fetch("http://localhost:8123/challenge");
Expand Down Expand Up @@ -96,5 +117,10 @@ window.onload = async () => {
return v;
}),
});
if (resp.ok) {
const {principal} = await resp.json();
loginButton.innerText = "Logged in!";
document.getElementById("principal")!.innerText = principal;
}
})
}

0 comments on commit 576183b

Please sign in to comment.