Skip to content

Commit 2699a63

Browse files
committed
🚸 E2E Example
1 parent 0c36d66 commit 2699a63

File tree

3 files changed

+115
-2
lines changed

3 files changed

+115
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ Please file a bug if you notice a violation of semantic versioning.
1818

1919
## [Unreleased]
2020
### Added
21+
- E2E example using mock test server added in v2.0.11
22+
- https://github.com/navikt/mock-oauth2-server
23+
- `docker compose -f docker-compose-ssl.yml up --wait`
24+
- `ruby examples/e2e.rb`
2125
- Apache SkyWalking Eyes dependency license check
2226
### Changed
2327
- Many improvements to make CI more resilient (past/future proof)

config-ssl.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@
33
"httpServer": {
44
"type": "NettyWrapper",
55
"ssl": {}
6-
}
7-
}
6+
},
7+
"clients": [
8+
{ "clientId": "demo-client", "clientSecret": "demo-secret" }
9+
]
10+
}

examples/e2e.rb

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# frozen_string_literal: true
2+
3+
# End-to-end example using oauth2 gem against a local mock-oauth2-server.
4+
# Prerequisites:
5+
# 1) Start the mock server (self-signed HTTPS on 8080):
6+
# docker compose -f docker-compose-ssl.yml up --wait
7+
# 2) Run this script:
8+
# ruby examples/e2e.rb
9+
# Notes:
10+
# - The mock server uses a self-signed certificate. SSL verification is disabled in this example.
11+
# - Tested down to Ruby 2.4 (avoid newer syntax).
12+
13+
require "oauth2"
14+
require "json"
15+
require "net/http"
16+
require "uri"
17+
18+
module E2E
19+
class ClientCredentialsDemo
20+
attr_reader :client_id, :client_secret, :issuer_base, :realm
21+
22+
# issuer_base: e.g., https://localhost:8080
23+
# realm: mock-oauth2-server issuer id ("default" by default)
24+
def initialize(client_id, client_secret, issuer_base, realm)
25+
@client_id = client_id
26+
@client_secret = client_secret
27+
@issuer_base = issuer_base
28+
@realm = realm
29+
end
30+
31+
def run
32+
well_known = discover
33+
token = fetch_token(well_known)
34+
puts "Access token (truncated): #{token.token[0, 20]}..."
35+
call_userinfo(well_known, token)
36+
puts "E2E complete"
37+
end
38+
39+
private
40+
41+
def discover
42+
discovery_url = File.join(@issuer_base, @realm, "/.well-known/openid-configuration")
43+
uri = URI(discovery_url)
44+
http = Net::HTTP.new(uri.host, uri.port)
45+
http.use_ssl = uri.scheme == "https"
46+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
47+
req = Net::HTTP::Get.new(uri.request_uri)
48+
res = http.request(req)
49+
unless res.code.to_i == 200
50+
raise "Discovery failed: #{res.code} #{res.message} - #{res.body}"
51+
end
52+
data = JSON.parse(res.body)
53+
# Expect token_endpoint and possibly userinfo_endpoint
54+
data
55+
end
56+
57+
def fetch_token(well_known)
58+
client = OAuth2::Client.new(
59+
@client_id,
60+
@client_secret,
61+
site: @issuer_base,
62+
token_url: URI.parse(well_known["token_endpoint"]).request_uri,
63+
ssl: {verify: false},
64+
auth_scheme: :request_body, # send client creds in request body (compatible default for mock servers)
65+
)
66+
# Use client_credentials grant
67+
client.client_credentials.get_token
68+
end
69+
70+
def call_userinfo(well_known, token)
71+
userinfo = well_known["userinfo_endpoint"]
72+
unless userinfo
73+
puts "No userinfo_endpoint advertised by server; skipping userinfo call."
74+
return
75+
end
76+
uri = URI(userinfo)
77+
http = Net::HTTP.new(uri.host, uri.port)
78+
http.use_ssl = uri.scheme == "https"
79+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
80+
req = Net::HTTP::Get.new(uri.request_uri)
81+
req["Authorization"] = "Bearer #{token.token}"
82+
res = http.request(req)
83+
puts "userinfo status: #{res.code} #{res.message}"
84+
if res.code.to_i == 200
85+
begin
86+
body = JSON.parse(res.body)
87+
rescue StandardError
88+
body = res.body
89+
end
90+
puts "userinfo body: #{body.inspect}"
91+
else
92+
puts "userinfo error body: #{res.body}"
93+
end
94+
end
95+
end
96+
end
97+
98+
if __FILE__ == $PROGRAM_NAME
99+
# These must match the mock server configuration (see config-ssl.json)
100+
client_id = ENV["E2E_CLIENT_ID"] || "demo-client"
101+
client_secret = ENV["E2E_CLIENT_SECRET"] || "demo-secret"
102+
issuer_base = ENV["E2E_ISSUER_BASE"] || "https://localhost:8080"
103+
realm = ENV["E2E_REALM"] || "default"
104+
105+
E2E::ClientCredentialsDemo.new(client_id, client_secret, issuer_base, realm).run
106+
end

0 commit comments

Comments
 (0)