Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ Style/StringLiterals:

Style/StringLiteralsInInterpolation:
EnforcedStyle: double_quotes

Layout/FirstHashElementIndentation:
EnforcedStyle: consistent

Style/TrailingCommaInHashLiteral:
EnforcedStyleForMultiline: comma

Metrics/BlockLength:
Max: 45

Layout/FirstArrayElementIndentation:
EnforcedStyle: consistent
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ gem "rake", "~> 13.0"

gem "minitest", "~> 5.16"

gem "debug"
gem "rubocop", "~> 1.21"
83 changes: 83 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
PATH
remote: .
specs:
vauth (0.1.0)
jwt (~> 3.1, >= 3.1.2)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.3)
base64 (0.3.0)
date (3.5.1)
debug (1.11.1)
irb (~> 1.10)
reline (>= 0.3.8)
erb (6.0.1)
io-console (0.8.2)
irb (1.16.0)
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
json (2.18.0)
jwt (3.1.2)
base64
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
minitest (5.27.0)
parallel (1.27.0)
parser (3.3.10.0)
ast (~> 2.4.1)
racc
pp (0.6.3)
prettyprint
prettyprint (0.2.0)
prism (1.7.0)
psych (5.3.1)
date
stringio
racc (1.8.1)
rainbow (3.1.1)
rake (13.3.1)
rdoc (7.0.3)
erb
psych (>= 4.0.0)
tsort
regexp_parser (2.11.3)
reline (0.6.3)
io-console (~> 0.5)
rubocop (1.82.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.48.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.49.0)
parser (>= 3.3.7.2)
prism (~> 1.7)
ruby-progressbar (1.13.0)
stringio (3.2.0)
tsort (0.2.0)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
debug
irb
minitest (~> 5.16)
rake (~> 13.0)
rubocop (~> 1.21)
vauth!

BUNDLED WITH
2.6.7
27 changes: 27 additions & 0 deletions bin/rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'rake' is installed as part of a gem, and
# this file is here to facilitate running it.
#

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

bundle_binstub = File.expand_path("bundle", __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("rake", "rake")
33 changes: 33 additions & 0 deletions lib/vauth/auth_code_grant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

require "json"
require "net/http"
require "vauth/identity_token"

module Vauth
class AuthCodeGrant # :nodoc:
def initialize(client, code)
@client = client
@code = code
end

def identity_token
::Vauth::IdentityToken.new(parsed_response["id_token"])
end

private

attr_reader :client, :code

def parsed_response
@parsed_response = JSON.parse(
::Net::HTTP.post_form(client.token_uri, {
client_id: client.id,
client_secret: client.secret,
scope: "openid",
code: code,
}).body
)
end
end
end
11 changes: 11 additions & 0 deletions lib/vauth/client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require "uri"

module Vauth
Client = Struct.new(:id, :secret, :token_uri) do
def token_uri
URI(self[:token_uri])
end
end
end
21 changes: 21 additions & 0 deletions lib/vauth/identity_token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

module Vauth
class IdentityToken # :nodoc:
def initialize(jwt_id_token)
@jwt_id_token = jwt_id_token
end

def issuer
JWT.decode(jwt_id_token, nil, true, { algorithm: "none" })[0]["iss"]
end

def subject
JWT.decode(jwt_id_token, nil, true, { algorithm: "none" })[0]["sub"]
end

private

attr_reader :jwt_id_token
end
end
4 changes: 0 additions & 4 deletions test/test_vauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,4 @@ class TestVauth < Minitest::Test
def test_that_it_has_a_version_number
refute_nil ::Vauth::VERSION
end

def test_it_does_something_useful
assert false
end
end
49 changes: 49 additions & 0 deletions test/vauth/auth_code_grant_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require "test_helper"
require "vauth/client"
require "vauth/auth_code_grant"
require "vauth/identity_token"

describe ::Vauth::AuthCodeGrant do
subject { ::Vauth::AuthCodeGrant.new(client, code) }

let(:client) { ::Vauth::Client.new(client_id, client_secret, token_uri) }
let(:code) { "code-for-auth-code-grant" }
let(:token_uri) { "https://oauth2-server.com/auth/token" }
let(:client_id) { "oauth2-server-given-client-id" }
let(:client_secret) { "oauth2-server-given-client-secret" }
let(:identity_token) { subject.identity_token }

describe "#identity_token" do
it "returns the Identity Token with the issuer and the subject" do
response_mock = Minitest::Mock.new
response_mock.expect(:body, JSON.dump({
id_token: JWT.encode({
iss: "issuer-from-identity-token",
sub: "subject-from-identity-token",
}, nil, "none"),
}))
net_http_mock = Minitest::Mock.new
net_http_mock.expect(:call, response_mock, [
URI(token_uri),
{
client_id: client_id,
client_secret: client_secret,
scope: "openid",
code: code,
}
])

::Net::HTTP.stub :post_form, net_http_mock do
_(identity_token).must_be_kind_of ::Vauth::IdentityToken

_(identity_token.issuer).must_equal "issuer-from-identity-token"
_(identity_token.subject).must_equal "subject-from-identity-token"
end

net_http_mock.verify
response_mock.verify
end
end
end
22 changes: 22 additions & 0 deletions test/vauth/client_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

require "test_helper"
require "uri"

require "vauth/client"

describe ::Vauth::Client do
subject do
::Vauth::Client.new(
"oauth2-server-given-client-id",
"oauth2-server-given-client-secret",
"https://oauth2-server.com/token"
)
end

describe "#token_uri" do
it "returns the passed Token URI" do
_(subject.token_uri).must_equal URI("https://oauth2-server.com/token")
end
end
end
29 changes: 29 additions & 0 deletions test/vauth/identity_token_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

require "test_helper"
require "jwt"

require "vauth/identity_token"

describe ::Vauth::IdentityToken do
let(:id_token_jwt) do
JWT.encode({
iss: "some-issuer-from-oauth2-provider",
sub: "some-subject-from-oauth2-provider",
}, nil, "none")
end

subject { ::Vauth::IdentityToken.new(id_token_jwt) }

describe "#issuer" do
it 'returns the "iss" value from the decoded JWT' do
_(subject.issuer).must_equal "some-issuer-from-oauth2-provider"
end
end

describe "#subject" do
it 'returns the "sub" value from the decoded JWT' do
_(subject.subject).must_equal "some-subject-from-oauth2-provider"
end
end
end
3 changes: 1 addition & 2 deletions vauth.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]

# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
spec.add_dependency "jwt", "~> 3.1", ">= 3.1.2"

# For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html
Expand Down