WIP verifying sig in the pre-registration endpoint
This commit is contained in:
parent
ef0e48a7ff
commit
2a4932ea34
7 changed files with 230 additions and 9 deletions
|
|
@ -21,7 +21,13 @@ class AuthorizationsController < ApplicationController
|
|||
|
||||
def token
|
||||
if(params[:type] == 'client_associate' && params[:manifest_url])
|
||||
client = OAuth2::Provider.client_class.create_from_manifest!(params[:manifest_url])
|
||||
manifest = JSON.parse(RestClient.get(params[:manifest_url]).body)
|
||||
|
||||
message = verify(params[:signed_string], params[:signature], manifest['public_key'])
|
||||
unless message =='ok'
|
||||
render :text => message, :status => 403
|
||||
else
|
||||
client = OAuth2::Provider.client_class.create_from_manifest!(manifest)
|
||||
|
||||
render :json => {:client_id => client.oauth_identifier,
|
||||
:client_secret => client.oauth_secret,
|
||||
|
|
@ -29,6 +35,7 @@ class AuthorizationsController < ApplicationController
|
|||
:flows_supported => "",
|
||||
}
|
||||
|
||||
end
|
||||
else
|
||||
render :text => "bad request", :status => 403
|
||||
end
|
||||
|
|
@ -45,11 +52,24 @@ class AuthorizationsController < ApplicationController
|
|||
auth.revoke
|
||||
redirect_to authorizations_path
|
||||
end
|
||||
|
||||
|
||||
def verify_signature(challenge, signature, serialized_pub_key)
|
||||
public_key = OpenSSL::PKey::RSA.new(serialized_pub_key)
|
||||
public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(signature), challenge)
|
||||
end
|
||||
|
||||
def valid_time?(time)
|
||||
time.to_i > (Time.now - 5.minutes).to_i
|
||||
end
|
||||
|
||||
def valid_nonce?(nonce)
|
||||
OAuth2::Provider.client_class.where(:nonce => nonce).first.nil?
|
||||
end
|
||||
end
|
||||
|
||||
OAuth2::Provider.client_class.instance_eval do
|
||||
def self.create_from_manifest! manifest_url
|
||||
manifest = JSON.parse(RestClient.get(manifest_url).body)
|
||||
def self.create_from_manifest! manifest
|
||||
create!(manifest)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
31
app/views/authorizations/index.html.haml
Normal file
31
app/views/authorizations/index.html.haml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
-# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
-# licensed under the Affero General Public License version 3 or later. See
|
||||
-# the COPYRIGHT file.
|
||||
|
||||
#section_header
|
||||
%h2
|
||||
= t('settings')
|
||||
= render 'shared/settings_nav'
|
||||
|
||||
.span-19.prepend-5.last
|
||||
%h2
|
||||
= t('_applications')
|
||||
|
||||
|
||||
#applications_stream.stream
|
||||
- for app in @applications
|
||||
|
||||
.stream_element{:id => app.id}
|
||||
.right
|
||||
= link_to t('delete'), authorization_path(:id => app.id), :method => :delete, :confirm => 'are you sure?'
|
||||
|
||||
- if app.icon_url
|
||||
= image_tag app.icon_url
|
||||
|
||||
.content
|
||||
%span.from
|
||||
= link_to app.name, app.homepage_url
|
||||
|
||||
.info
|
||||
= app.description
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
class AddNonceAndPublicKeyToOauthClients < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :oauth_clients, :nonce, :string
|
||||
add_column :oauth_clients, :public_key, :text
|
||||
add_index :oauth_clients, :nonce
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :oauth_clients, :nonce
|
||||
remove_column :oauth_clients, :public_key
|
||||
remove_index :oauth_clients, :nonce
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20110603212633) do
|
||||
ActiveRecord::Schema.define(:version => 20110614005205) do
|
||||
|
||||
create_table "aspect_memberships", :force => true do |t|
|
||||
t.integer "aspect_id", :null => false
|
||||
|
|
@ -228,9 +228,12 @@ ActiveRecord::Schema.define(:version => 20110603212633) do
|
|||
t.text "description"
|
||||
t.string "homepage_url"
|
||||
t.string "icon_url"
|
||||
t.string "nonce"
|
||||
t.text "public_key"
|
||||
end
|
||||
|
||||
add_index "oauth_clients", ["name"], :name => "index_oauth_clients_on_name", :unique => true
|
||||
add_index "oauth_clients", ["nonce"], :name => "index_oauth_clients_on_nonce"
|
||||
|
||||
create_table "people", :force => true do |t|
|
||||
t.string "guid", :null => false
|
||||
|
|
|
|||
15
spec/chubbies/chubbies.private.pem
Normal file
15
spec/chubbies/chubbies.private.pem
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQC6PThqopA0Sv1ZrWp+wKz6SPQwWzS2IEGRV1eBE2LEvMk5K2MK
|
||||
jZqDF6SeolCPQsDww03qIxbtzXiVFtjBaiDw+fLpbnX3VcfoMlfV3IKMPjD8eFUE
|
||||
2ke3tJzHeXLfXhHq5ubX1PrXcsNwHeNrtvviv9G2BhYMjwi49T0YS27rhwIDAQAB
|
||||
AoGAUxEhS7asWRalf80wdc6cmJnXiIX1sdIbTKdHWUP7RsLpgX1PlJJqO1RdUYAW
|
||||
LH/arMh/xRHXlUOTJ/Rjw4kBnZZpPmKpAmkefqi7ZRTvDNj/aVW2DMi6TGU0lpMV
|
||||
TyXKZtO69FK5uFle/I7nftGuUiVAkPIXMrnXM1oxPjCkUWECQQDuNR6JcxCF+Ioj
|
||||
bQlemHfwRLyfbAumeXkYyBxdfYu7Sonx+xjptacwWyHTnLaFeoEIAjvrjT0fDNym
|
||||
QZA0YAnxAkEAyCZjmMwacCGxYxIWiVDfMBCt1fSOQzOAYCVz12ltW1GkUh1kt1p+
|
||||
4ui/q38RGu9s4RRxb7h0WNHtKfU/t2aU9wJAXiKZ1cGmFvt4Q7W0TTC9vTK8w9ej
|
||||
5v78LyHtq7iQfsxfJUSQvNMvpfltrb2xl6Ao26xeV6DyNZIUpJMmVLxbUQJBAJfi
|
||||
cfAw6tsu5lL9FfcMVOI/tftIA3FBsujDYx4T1jXXRbA+uABf/ywoXdNBsPRUvrYr
|
||||
ck3KlxgT7jrJ7pk5kk8CQCqtJ1U6RlTTKY0jnwOASSCDctGhTXQWj44/xyGjJF7I
|
||||
4eHuL18xQTjB3Ag+VRK/z8W5mqfgzonotrhc0pSXxvM=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
6
spec/chubbies/chubbies.public.pem
Normal file
6
spec/chubbies/chubbies.public.pem
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6PThqopA0Sv1ZrWp+wKz6SPQw
|
||||
WzS2IEGRV1eBE2LEvMk5K2MKjZqDF6SeolCPQsDww03qIxbtzXiVFtjBaiDw+fLp
|
||||
bnX3VcfoMlfV3IKMPjD8eFUE2ke3tJzHeXLfXhHq5ubX1PrXcsNwHeNrtvviv9G2
|
||||
BhYMjwi49T0YS27rhwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
133
spec/controllers/authorizations_controller_spec.rb
Normal file
133
spec/controllers/authorizations_controller_spec.rb
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe AuthorizationsController do
|
||||
before do
|
||||
sign_in :user, alice
|
||||
@controller.stub(:current_user).and_return(alice)
|
||||
|
||||
end
|
||||
|
||||
describe '#token' do
|
||||
before do
|
||||
manifest = {
|
||||
"name" => "Chubbies",
|
||||
"description" => "The best way to chub.",
|
||||
"homepage_url" => "http://chubbi.es/",
|
||||
"icon_url" => "#",
|
||||
'public_key' => 'public_key!'
|
||||
}.to_json
|
||||
|
||||
stub_request(:get, "http://chubbi.es/manifest.json").
|
||||
to_return(:status => 200, :body => manifest, :headers => {})
|
||||
|
||||
@params_hash = {:type => 'client_associate', :manifest_url => "http://chubbi.es/manifest.json" }
|
||||
end
|
||||
|
||||
it 'fetches the manifest' do
|
||||
post :token, @params_hash
|
||||
end
|
||||
|
||||
it 'creates a client application' do
|
||||
lambda {
|
||||
post :token, @params_hash
|
||||
}.should change(OAuth2::Provider.client_class, :count).by(1)
|
||||
end
|
||||
|
||||
it 'verifies the signable string validity(time,nonce,sig)' do
|
||||
post :token, @params_hash.merge!({:signed_string => 'signable_string', :signature => 'sig'})
|
||||
@controller.should_receive(:verify).with('signable_string', 'sig', 'public_key!')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#index" do
|
||||
it 'succeeds' do
|
||||
get :index
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it 'assigns the auth. & apps for the current user' do
|
||||
app1 = OAuth2::Provider.client_class.create(:name => "Authorized App")
|
||||
app2 = OAuth2::Provider.client_class.create(:name => "Unauthorized App")
|
||||
auth1 = OAuth2::Provider.authorization_class.create(:client => app1, :resource_owner => alice)
|
||||
auth2 = OAuth2::Provider.authorization_class.create(:client => app1, :resource_owner => bob)
|
||||
auth3 = OAuth2::Provider.authorization_class.create(:client => app2, :resource_owner => bob)
|
||||
|
||||
get :index
|
||||
assigns[:authorizations].should == [auth1]
|
||||
assigns[:applications].should == [app1]
|
||||
end
|
||||
end
|
||||
|
||||
describe "#destroy" do
|
||||
before do
|
||||
@app1 = OAuth2::Provider.client_class.create(:name => "Authorized App")
|
||||
@auth1 = OAuth2::Provider.authorization_class.create(:client => @app1, :resource_owner => alice)
|
||||
@auth2 = OAuth2::Provider.authorization_class.create(:client => @app1, :resource_owner => bob)
|
||||
end
|
||||
it 'deletes an authorization' do
|
||||
lambda{
|
||||
delete :destroy, :id => @app1.id
|
||||
}.should change(OAuth2::Provider.authorization_class, :count).by(-1)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#verify' do
|
||||
it 'checks for valid time'
|
||||
it 'checks the signature'
|
||||
it 'checks for valid nonce'
|
||||
end
|
||||
|
||||
describe '#verify_signature' do
|
||||
before do
|
||||
@private_key = OpenSSL::PKey::RSA.new(File.read(Rails.root + "spec/chubbies/chubbies.private.pem"))
|
||||
|
||||
@signable_string = ["http://chubbi.es/",'http://pod.pod/',"#{Time.now.to_i}",'asdfsfasf'].join(';')
|
||||
@sig = @private_key.sign(OpenSSL::Digest::SHA256.new, @signable_string)
|
||||
end
|
||||
|
||||
it 'returns true if the signature is valid' do
|
||||
@public_key = File.read(Rails.root + "spec/chubbies/chubbies.public.pem")
|
||||
@controller.verify_signature(@signable_string, Base64.encode64(@sig), @public_key).should be_true
|
||||
end
|
||||
|
||||
it 'returns false if the signature is invalid' do
|
||||
@signable_string = "something else"
|
||||
|
||||
@public_key = File.read(Rails.root + "spec/chubbies/chubbies.public.pem")
|
||||
@controller.verify_signature(@signable_string, Base64.encode64(@sig), @public_key).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe "valid_time?" do
|
||||
before do
|
||||
@time = Time.now
|
||||
Time.stub(:now).and_return(@time)
|
||||
end
|
||||
|
||||
it "returns true if time is within the last 5 minutes" do
|
||||
@controller.valid_time?(@time - 4.minutes - 59.seconds).should be_true
|
||||
end
|
||||
|
||||
it "returns false if time is not within the last 5 minutes" do
|
||||
@controller.valid_time?(@time - 5.minutes - 1.seconds).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe 'valid_nonce' do
|
||||
before do
|
||||
@app1 = OAuth2::Provider.client_class.create(:name => "Authorized App", :nonce => "abc123")
|
||||
end
|
||||
|
||||
it 'returns true if its a new nonce' do
|
||||
@controller.valid_nonce?("lalalala").should be_true
|
||||
end
|
||||
|
||||
it 'returns false if the nonce was already used' do
|
||||
@controller.valid_nonce?("abc123").should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue