Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit 8ccbce1

Browse files
committed
2 parents cd837eb + 7645fb2 commit 8ccbce1

File tree

8 files changed

+136
-66
lines changed

8 files changed

+136
-66
lines changed

.github/CODEOWNERS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Default global owners for example-go
2+
* @calhorn95 @dylanbrookes

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.15
1+
FROM golang:1.15-alpine
22

33
WORKDIR /app
44

README.md

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,40 @@
22

33
Passage provides an SDK to easily authenticate HTTP requests. Example source code can be found on GitHub, [here](https://github.com/passageidentity/example-go).
44

5+
### Setup
6+
7+
For this example app, we'll need to provide our application with a Passage App ID and API Key. Your App ID and API Key can be found in the [Passage Console](https://console.passage.id) in your App Settings. You'll need to set the following environment variables with your respective credentials:
8+
9+
```bash
10+
PASSAGE_APP_ID=
11+
PASSAGE_API_KEY=
12+
PORT=5000
13+
```
14+
15+
### Run With Go
16+
17+
To run this example app, make sure you have [Go installed on your computer](https://golang.org/doc/install).
18+
19+
Run the following command:
20+
21+
```bash
22+
go run main.go
23+
```
24+
25+
### Run With Docker
26+
27+
Create your docker image with the following command:
28+
29+
```bash
30+
$ docker build -t example-go .
31+
```
32+
33+
Run your docker container using the example-go image:
34+
35+
```bash
36+
$ docker run -p 5000:5000 example-go
37+
```
38+
539
### Authenticating an HTTP Request
640

741
A Go server can easily authenticate an HTTP request using the Passage SDK, as shown below.
@@ -16,7 +50,7 @@ import (
1650
func exampleHandler(w http.ResponseWriter, r *http.Request) {
1751

1852
// Authenticate this request using the Passage SDK.
19-
psg := passage.New("<Passage App Handle>")
53+
psg := passage.New("<Passage App ID>")
2054
_, err := psg.AuthenticateRequest(r)
2155
if err != nil {
2256
w.WriteHeader(http.StatusUnauthorized)
@@ -30,22 +64,22 @@ func exampleHandler(w http.ResponseWriter, r *http.Request) {
3064

3165
### Authorizing a User
3266

33-
It is important to remember that the `psg.AuthenticateRequest()` function validates that a request is properly authenticated, but makes no assertions about *who* it is authorized for. To perform an authorization check, the Passage User Handle can be referenced.
67+
It is important to remember that the `psg.AuthenticateRequest()` function validates that a request is properly authenticated, but makes no assertions about _who_ it is authorized for. To perform an authorization check, the Passage User Handle can be referenced.
3468

3569
```go
3670
func exampleHandler(w http.ResponseWriter, r *http.Request) {
3771

3872
// Authenticate this request using the Passage SDK.
39-
psg := passage.New("<Passage App Handle>")
40-
passageHandle, err := psg.AuthenticateRequest(r)
73+
psg := passage.New("<Passage App ID>")
74+
passageUserID, err := psg.AuthenticateRequest(r)
4175
if err != nil {
4276
w.WriteHeader(http.StatusUnauthorized)
4377
return
4478
}
4579

4680
// Check that the user with `passageHandle` is allowed to perform
4781
// a certain action on a certain resource.
48-
err = authorizationCheck(passageHandle)
82+
err = authorizationCheck(passageUserID)
4983
if err != nil {
5084
w.WriteHeader(http.StatusUnauthorized)
5185
return
@@ -57,19 +91,21 @@ func exampleHandler(w http.ResponseWriter, r *http.Request) {
5791
```
5892

5993
## Get User
60-
To get user information, you can use the Passage SDK with an API key. This will authenticate your web server to Passage and grant you management
61-
access to user information. API keys should never be hard-coded in source code, but stored in environment variables or a secrets storage mechanism.
94+
95+
To get user information, you can use the Passage SDK with an API key. This will authenticate your web server to Passage and grant you management
96+
access to user information. API keys should never be hard-coded in source code, but stored in environment variables or a secrets storage mechanism.
97+
6298
```go
6399

64-
psg := passage.New("<Passage App Handle>", "<API_KEY>")
65-
passageHandle, err := psg.AuthenticateRequest(r)
100+
psg := passage.New("<Passage App ID>", "<API_KEY>")
101+
passageUserID, err := psg.AuthenticateRequest(r)
66102
if err != nil {
67103
w.WriteHeader(http.StatusUnauthorized)
68104
return
69105
}
70-
106+
71107
//information regarding the user will exist in the user variable
72-
user, err := psg.GetUser(passageHandle)
108+
user, err := psg.GetUser(passageUserID)
73109
if err != nil {
74110
fmt.Println("Could not get user: ", err)
75111
return
@@ -82,8 +118,8 @@ The easiest way to add authentication to a web frontend is with a Passage Elemen
82118

83119
```html
84120
<!-- Passage will populate this custom element with a complete authentication UI/UX. -->
85-
<passage-auth app-id="<Passage App Handle>"></passage-auth>
121+
<passage-auth app-id="<Passage App ID>"></passage-auth>
86122

87123
<!-- Include the passage-web JavaScript from the Passage CDN. -->
88124
<script src="https://cdn.passage.id/passage-web.js"></script>
89-
```
125+
```

go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module github.com/passageidentity/example-go
22

33
go 1.15
44

5-
require github.com/passageidentity/passage-go v1.1.4-0.20220218163302-b39181e3aa63 // indirect
5+
require (
6+
github.com/joho/godotenv v1.4.0
7+
github.com/passageidentity/passage-go v1.1.4-0.20220218163302-b39181e3aa63
8+
)

go.sum

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8
22
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
33
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
44
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
5+
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
56
github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
6-
github.com/passageidentity/passage-go v1.1.1 h1:nfc29QFPOhFrdcKr9pU5K4pVhsI+aWxtSxLSWjX4GPE=
7-
github.com/passageidentity/passage-go v1.1.1/go.mod h1:UvFvzPuSKx16jwWXti/JIaW9+3MfJw2fE+PbMV43I5I=
8-
github.com/passageidentity/passage-go v1.1.3 h1:u9dDsyuZUz8T6osXoafG4f3d6YDEpZbOFrwluH16PsI=
9-
github.com/passageidentity/passage-go v1.1.3/go.mod h1:bXWdkaW7wJ8Aq4qGalP22UaGxqzzud1+4nDxhJRZuPw=
107
github.com/passageidentity/passage-go v1.1.4-0.20220218163302-b39181e3aa63 h1:asg2XadY5lbNEZwrN8vTSuziIFly4FoEKWd0emI9tLE=
118
github.com/passageidentity/passage-go v1.1.4-0.20220218163302-b39181e3aa63/go.mod h1:bXWdkaW7wJ8Aq4qGalP22UaGxqzzud1+4nDxhJRZuPw=
129
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

main.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,36 @@ package main
22

33
import (
44
"fmt"
5+
"log"
56
"net/http"
67
"os"
78
"text/template"
89

10+
"github.com/joho/godotenv"
911
"github.com/passageidentity/passage-go"
1012
)
1113

1214
func main() {
15+
err := godotenv.Load(".env")
16+
if err != nil {
17+
log.Fatal("Failed to read .env variables")
18+
}
19+
20+
port := os.Getenv("PORT")
21+
if port == "" {
22+
log.Fatal("PORT environment variable required")
23+
}
24+
1325
http.HandleFunc("/", indexHandler)
1426
http.HandleFunc("/dashboard", dashboardHandler)
1527
http.Handle("/assets/", http.FileServer(http.Dir("./templates")))
1628

17-
http.ListenAndServe(":"+os.Getenv("PORT"), nil)
29+
http.ListenAndServe(":"+port, nil)
1830
}
1931

2032
func indexHandler(w http.ResponseWriter, r *http.Request) {
21-
http.ServeFile(w, r, "templates/index.html")
33+
inputArgs := map[string]interface{}{"appID": os.Getenv("PASSAGE_APP_ID")}
34+
outputHTML(w, "templates/index.html", inputArgs)
2235
}
2336

2437
func outputHTML(w http.ResponseWriter, filename string, data interface{}) {
@@ -35,7 +48,7 @@ func outputHTML(w http.ResponseWriter, filename string, data interface{}) {
3548

3649
func dashboardHandler(w http.ResponseWriter, r *http.Request) {
3750
// Authenticate this request using the Passage SDK.
38-
psg, err := passage.New("KZ520QJSiFRLvbBvraaAgYuf", &passage.Config{APIKey: os.Getenv("PASSAGE_API_KEY")})
51+
psg, err := passage.New(os.Getenv("PASSAGE_APP_ID"), &passage.Config{APIKey: os.Getenv("PASSAGE_API_KEY")})
3952
if err != nil {
4053
fmt.Println("Cannot create psg: ", err)
4154
}
@@ -50,6 +63,12 @@ func dashboardHandler(w http.ResponseWriter, r *http.Request) {
5063
fmt.Println("Could not get user: ", err)
5164
return
5265
}
53-
inputArgs := map[string]interface{}{"email": user.Email}
66+
var identifier string
67+
if user.Email != "" {
68+
identifier = user.Email
69+
} else {
70+
identifier = user.Phone
71+
}
72+
inputArgs := map[string]interface{}{"identifier": identifier}
5473
outputHTML(w, "templates/dashboard.html", inputArgs)
5574
}

templates/dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<div class="bg-poly"></div>
2323

2424
<div class=header>
25-
{{.email}} signed in
25+
{{.identifier}} signed in
2626
<br>
2727
with <strong>Passage.</strong>
2828
</div>

templates/index.html

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,61 @@
11
<!DOCTYPE html>
22
<html lang="en">
3-
<head>
4-
<meta charset="UTF-8">
5-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@300&display=swap" rel="stylesheet">
8-
<link href="https://fonts.googleapis.com/css2?family=Lexend+Deca&display=swap" rel="stylesheet">
9-
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
10-
<link rel="stylesheet" href="assets/style.css">
11-
<link rel="stylesheet" href="assets/index.css">
12-
<title>Try Passage</title>
13-
<script async src="https://www.googletagmanager.com/gtag/js?id=G-B8V1R3HRNB"></script>
14-
<script>
15-
window.dataLayer = window.dataLayer || [];
16-
function gtag(){dataLayer.push(arguments);}
17-
gtag('js', new Date());
18-
gtag('config', 'G-B8V1R3HRNB');
19-
</script>
20-
</head>
21-
<body>
22-
<div class="bg-poly"></div>
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<link
8+
href="https://fonts.googleapis.com/css2?family=Nunito:wght@300&display=swap"
9+
rel="stylesheet"
10+
/>
11+
<link
12+
href="https://fonts.googleapis.com/css2?family=Lexend+Deca&display=swap"
13+
rel="stylesheet"
14+
/>
15+
<link
16+
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
17+
rel="stylesheet"
18+
integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x"
19+
crossorigin="anonymous"
20+
/>
21+
<link rel="stylesheet" href="assets/style.css" />
22+
<link rel="stylesheet" href="assets/index.css" />
23+
<title>Try Passage</title>
24+
<script
25+
async
26+
src="https://www.googletagmanager.com/gtag/js?id=G-B8V1R3HRNB"
27+
></script>
28+
<script>
29+
window.dataLayer = window.dataLayer || [];
30+
function gtag() {
31+
dataLayer.push(arguments);
32+
}
33+
gtag("js", new Date());
34+
gtag("config", "G-B8V1R3HRNB");
35+
</script>
36+
</head>
37+
<body>
38+
<div class="bg-poly"></div>
2339

24-
<div class=header>
25-
build amazing things
26-
<br>
27-
with <strong>Passage.</strong>
28-
</div>
29-
30-
<div class="form-container">
31-
<!-- Passage will populate this custom element with a complete authentication UI/UX. -->
32-
<passage-auth app-id="KZ520QJSiFRLvbBvraaAgYuf"></passage-auth>
33-
<!-- Include the passage-web JavaScript from the Passage CDN. -->
34-
<script src="https://cdn.passage.id/passage-web.js"></script>
35-
</div>
40+
<div class="header">
41+
build amazing things
42+
<br />
43+
with <strong>Passage.</strong>
44+
</div>
3645

37-
<div class="footer">
38-
Implement awesome authentication with two lines of code.
39-
<br>
40-
<a href="https://passage.id">
41-
<button class="btn btn-lg">
42-
Request Early Access
43-
</button>
44-
</a>
45-
</div>
46+
<div class="form-container">
47+
<!-- Passage will populate this custom element with a complete authentication UI/UX. -->
48+
<passage-auth app-id="{{.appID}}"></passage-auth>
49+
<!-- Include the passage-web JavaScript from the Passage CDN. -->
50+
<script src="https://cdn.passage.id/passage-web.js"></script>
51+
</div>
4652

47-
</body>
53+
<div class="footer">
54+
Implement awesome authentication with two lines of code.
55+
<br />
56+
<a href="https://passage.id">
57+
<button class="btn btn-lg">Request Early Access</button>
58+
</a>
59+
</div>
60+
</body>
4861
</html>

0 commit comments

Comments
 (0)