├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── examples └── sinatra.rb ├── lib ├── omniauth-azure-oauth2.rb └── omniauth │ ├── azure_oauth2.rb │ ├── azure_oauth2 │ └── version.rb │ └── strategies │ └── azure_oauth2.rb ├── omniauth-azure-oauth2.gemspec └── spec ├── omniauth └── strategies │ └── azure_oauth2_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | .ruby-gemset 7 | .ruby-version 8 | Gemfile.lock 9 | InstalledFiles 10 | _yardoc 11 | coverage 12 | doc/ 13 | lib/bundler/man 14 | pkg 15 | rdoc 16 | spec/reports 17 | test/tmp 18 | test/version_tmp 19 | tmp 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.1.8 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version 0.0.10 2 | * Expand JWT dep. Thanks @ronaldsalas 3 | 4 | # Version 0.0.9 5 | * Added support for dynamic tenant urls. Thanks @marcus-fellinger-esc 6 | 7 | # Version 0.0.8 8 | * Upgrade to omniauth-oauth2 1.4.0 and fix callback url issue 9 | * Allow prompt parameter, thanks @hilu 10 | * Add tenant id to info 11 | * Updated base url 12 | 13 | # Version 0.0.6 14 | * Use 'name' from Azure for name, and 'unique_name' for nickname per Auth Hash spec. Thanks @jayme-github 15 | 16 | # Version 0.0.5 17 | * loosen jwt requirement 18 | 19 | # Version 0.0.5 20 | * loosen jwt requirement 21 | 22 | # VERSION 0.0.4 23 | * fix for JWT scoping, thanks @tobsher 24 | 25 | # VERSION 0.0.3 26 | * added common endpoint and removed mandatory requirement for tenant-id 27 | * upgraded jwt 28 | 29 | # VERSION 0.0.1 30 | 31 | * Initial build 32 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in omniauth-azure-oauth2.gemspec 4 | gemspec 5 | 6 | group :example do 7 | gem 'sinatra' 8 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Deltek 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # No longer maintained 2 | This project is no longer maintained. I'm off on other projects on other platforms and don't have time to maintain this gem :/ I am unable to transfer the project ownership. Your best bet is to fork and apply your changes. Perhaps consider publishing to RubyGems yourself so it can live on. 3 | 4 | # OmniAuth Windows Azure Active Directory Strategy 5 | [![Build Status](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2.svg?branch=master)](https://travis-ci.org/KonaTeam/omniauth-azure-oauth2) 6 | 7 | This gem provides a simple way to authenticate to Windows Azure Active Directory (WAAD) over OAuth2 using OmniAuth. 8 | 9 | One of the unique challenges of WAAD OAuth is that WAAD is multi tenant. Any given tenant can have multiple active 10 | directories. The CLIENT-ID, REPLY-URL and keys will be unique to the tenant/AD/application combination. This gem simply 11 | provides hooks for determining those unique values for each call. 12 | 13 | ## Installation 14 | 15 | Add this line to your application's Gemfile: 16 | 17 | ```ruby 18 | gem 'omniauth-azure-oauth2' 19 | ``` 20 | 21 | ## Usage 22 | 23 | First, you will need to add your site as an application in WAAD.: 24 | [Adding, Updating, and Removing an Application](http://msdn.microsoft.com/en-us/library/azure/dn132599.aspx) 25 | 26 | Summary: 27 | Select your Active Directory in https://manage.windowsazure.com/ of type 'Web Application'. Name, sign-on url, 28 | logo are not important. You will need the CLIENT-ID from the application configuration and you will need to generate 29 | an expiring key (aka 'client secret'). REPLY URL is the oauth redirect uri which will be the omniauth callback path 30 | https://example.com/users/auth/azure_oauth2/callback. The APP ID UI just needs to be unique to that tenant and identify 31 | your site and isn't needed to configure the gem. 32 | Permissions need Delegated Permissions to at least have "Enable sign-on and read user's profiles". 33 | 34 | Note: Seems like the terminology is still fluid, so follow the MS guidance (buwahaha) to set this up. 35 | 36 | The TenantInfo information can be a hash or class. It must provide client_id and client_secret. 37 | Optionally a domain_hint and tenant_id. For a simple single-tenant app, this could be: 38 | 39 | ```ruby 40 | use OmniAuth::Builder do 41 | provider :azure_oauth2, 42 | { 43 | client_id: ENV['AZURE_CLIENT_ID'], 44 | client_secret: ENV['AZURE_CLIENT_SECRET'], 45 | tenant_id: ENV['AZURE_TENANT_ID'] 46 | } 47 | end 48 | ``` 49 | 50 | Or the alternative format for use with [devise](https://github.com/plataformatec/devise): 51 | 52 | ```ruby 53 | config.omniauth :azure_oauth2, client_id: ENV['AZURE_CLIENT_ID'], 54 | client_secret: ENV['AZURE_CLIENT_SECRET'], tenant_id: ENV['AZURE_TENANT_ID'] 55 | ``` 56 | 57 | For multi-tenant apps where you don't know the tenant_id in advance, simply leave out the tenant_id to use the 58 | [common endpoint](http://msdn.microsoft.com/en-us/library/azure/dn645542.aspx). 59 | 60 | ```ruby 61 | use OmniAuth::Builder do 62 | provider :azure_oauth2, 63 | { 64 | client_id: ENV['AZURE_CLIENT_ID'], 65 | client_secret: ENV['AZURE_CLIENT_SECRET'] 66 | } 67 | end 68 | ``` 69 | 70 | For dynamic tenant assignment, pass a class that supports those same attributes and accepts the strategy as a parameter 71 | 72 | ```ruby 73 | class YouTenantProvider 74 | def initialize(strategy) 75 | @strategy = strategy 76 | end 77 | 78 | def client_id 79 | tenant.azure_client_id 80 | end 81 | 82 | def client_secret 83 | tenant.azure_client_secret 84 | end 85 | 86 | def tenant_id 87 | tenant.azure_tanant_id 88 | end 89 | 90 | def domain_hint 91 | tenant.azure_domain_hint 92 | end 93 | 94 | private 95 | 96 | def tenant 97 | # whatever strategy you want to figure out the right tenant from params/session 98 | @tenant ||= Customer.find(@strategy.session[:customer_id]) 99 | end 100 | end 101 | 102 | use OmniAuth::Builder do 103 | provider :azure_oauth2, YourTenantProvider 104 | end 105 | ``` 106 | 107 | The base_azure_url can be overridden in the provider configuration for different locales; e.g. `base_azure_url: "https://login.microsoftonline.de"` 108 | 109 | 110 | ## Auth Hash Schema 111 | 112 | The following information is provided back to you for this provider: 113 | 114 | ```ruby 115 | { 116 | uid: '12345', 117 | info: { 118 | name: 'some one', 119 | first_name: 'some', 120 | last_name: 'one', 121 | email: 'someone@example.com' 122 | }, 123 | credentials: { 124 | token: 'thetoken', 125 | refresh_token: 'refresh' 126 | }, 127 | extra: { raw_info: raw_api_response } 128 | } 129 | ``` 130 | ## notes 131 | 132 | When you make a request to WAAD you must specify a resource. The gem currently assumes this is the AD identified as '00000002-0000-0000-c000-000000000000'. 133 | This can be passed in as part of the config. It currently isn't designed to be dynamic. 134 | 135 | ```ruby 136 | use OmniAuth::Builder do 137 | provider :azure_oauth2, TenantInfo, resource: 'myresource' 138 | end 139 | ``` 140 | 141 | ## Contributing 142 | 143 | 1. Fork it 144 | 2. Create your feature branch (`git checkout -b my-new-feature`) 145 | 3. Make your changes, add tests, run tests (`rake`) 146 | 4. Commit your changes and tests (`git commit -am 'Added some feature'`) 147 | 5. Push to the branch (`git push origin my-new-feature`) 148 | 6. Create new Pull Request 149 | 150 | 151 | ## Misc 152 | Run tests `bundle exec rake` 153 | Push to rubygems `bundle exec rake release`. 154 | 155 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require File.join('bundler', 'gem_tasks') 2 | require File.join('rspec', 'core', 'rake_task') 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | task :default => :spec -------------------------------------------------------------------------------- /examples/sinatra.rb: -------------------------------------------------------------------------------- 1 | $:.push File.dirname(__FILE__) + '/../lib' 2 | 3 | require 'omniauth-azure-oauth2' 4 | require 'sinatra' 5 | 6 | class MyAzureProvider 7 | def self.client_id 8 | ENV['AZURE_CLIENT_ID'] 9 | end 10 | 11 | def self.client_secret 12 | ENV['AZURE_CLIENT_SECRET'] 13 | end 14 | 15 | def self.tenant_id 16 | ENV['AZURE_TENANT_ID'] 17 | end 18 | 19 | end 20 | 21 | use Rack::Session::Cookie 22 | use OmniAuth::Strategies::Azure, MyAzureProvider 23 | 24 | get '/' do 25 | "Log in with Azure" 26 | end 27 | 28 | get '/auth/azure_oauth2/callback' do 29 | content_type 'text/plain' 30 | request.env['omniauth.auth'].inspect 31 | end -------------------------------------------------------------------------------- /lib/omniauth-azure-oauth2.rb: -------------------------------------------------------------------------------- 1 | require File.join('omniauth', 'azure_oauth2') -------------------------------------------------------------------------------- /lib/omniauth/azure_oauth2.rb: -------------------------------------------------------------------------------- 1 | require File.join('omniauth', 'strategies', 'azure_oauth2') -------------------------------------------------------------------------------- /lib/omniauth/azure_oauth2/version.rb: -------------------------------------------------------------------------------- 1 | module OmniAuth 2 | module AzureOauth2 3 | VERSION = "0.0.10" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/omniauth/strategies/azure_oauth2.rb: -------------------------------------------------------------------------------- 1 | require 'omniauth/strategies/oauth2' 2 | require 'jwt' 3 | 4 | module OmniAuth 5 | module Strategies 6 | class AzureOauth2 < OmniAuth::Strategies::OAuth2 7 | BASE_AZURE_URL = 'https://login.microsoftonline.com' 8 | 9 | option :name, 'azure_oauth2' 10 | 11 | option :tenant_provider, nil 12 | 13 | # AD resource identifier 14 | option :resource, '00000002-0000-0000-c000-000000000000' 15 | 16 | # tenant_provider must return client_id, client_secret and optionally tenant_id and base_azure_url 17 | args [:tenant_provider] 18 | 19 | def client 20 | if options.tenant_provider 21 | provider = options.tenant_provider.new(self) 22 | else 23 | provider = options # if pass has to config, get mapped right on to options 24 | end 25 | 26 | options.client_id = provider.client_id 27 | options.client_secret = provider.client_secret 28 | options.tenant_id = 29 | provider.respond_to?(:tenant_id) ? provider.tenant_id : 'common' 30 | options.base_azure_url = 31 | provider.respond_to?(:base_azure_url) ? provider.base_azure_url : BASE_AZURE_URL 32 | 33 | options.authorize_params = provider.authorize_params if provider.respond_to?(:authorize_params) 34 | options.authorize_params.domain_hint = provider.domain_hint if provider.respond_to?(:domain_hint) && provider.domain_hint 35 | options.authorize_params.prompt = request.params['prompt'] if defined? request && request.params['prompt'] 36 | options.client_options.authorize_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/authorize" 37 | options.client_options.token_url = "#{options.base_azure_url}/#{options.tenant_id}/oauth2/token" 38 | super 39 | end 40 | 41 | uid { 42 | raw_info['sub'] 43 | } 44 | 45 | info do 46 | { 47 | name: raw_info['name'], 48 | nickname: raw_info['unique_name'], 49 | first_name: raw_info['given_name'], 50 | last_name: raw_info['family_name'], 51 | email: raw_info['email'] || raw_info['upn'], 52 | oid: raw_info['oid'], 53 | tid: raw_info['tid'] 54 | } 55 | end 56 | 57 | def token_params 58 | azure_resource = request.env['omniauth.params'] && request.env['omniauth.params']['azure_resource'] 59 | super.merge(resource: azure_resource || options.resource) 60 | end 61 | 62 | def callback_url 63 | full_host + script_name + callback_path 64 | end 65 | 66 | def raw_info 67 | # it's all here in JWT http://msdn.microsoft.com/en-us/library/azure/dn195587.aspx 68 | @raw_info ||= ::JWT.decode(access_token.token, nil, false).first 69 | end 70 | 71 | end 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /omniauth-azure-oauth2.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | require File.expand_path(File.join('..', 'lib', 'omniauth', 'azure_oauth2', 'version'), __FILE__) 3 | 4 | Gem::Specification.new do |gem| 5 | gem.authors = ["Mark Nadig"] 6 | gem.email = ["mark@nadigs.net"] 7 | gem.description = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth} 8 | gem.summary = %q{An Windows Azure Active Directory OAuth2 strategy for OmniAuth} 9 | gem.homepage = "https://github.com/KonaTeam/omniauth-azure-oauth2" 10 | 11 | gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 12 | gem.files = `git ls-files`.split("\n") 13 | gem.test_files = `git ls-files -- {spec}/*`.split("\n") 14 | gem.name = "omniauth-azure-oauth2" 15 | gem.require_paths = ["lib"] 16 | gem.version = OmniAuth::AzureOauth2::VERSION 17 | gem.license = "MIT" 18 | 19 | gem.add_dependency 'omniauth', '~> 1.0' 20 | gem.add_dependency 'jwt', ['>= 1.0', '< 3.0'] 21 | 22 | gem.add_runtime_dependency 'omniauth-oauth2', '~> 1.4' 23 | 24 | gem.add_development_dependency 'rspec', '>= 2.14.0' 25 | gem.add_development_dependency 'rake' 26 | end 27 | -------------------------------------------------------------------------------- /spec/omniauth/strategies/azure_oauth2_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'omniauth-azure-oauth2' 3 | 4 | module OmniAuth 5 | module Strategies 6 | module JWT; end 7 | end 8 | end 9 | 10 | describe OmniAuth::Strategies::AzureOauth2 do 11 | let(:request) { double('Request', :params => {}, :cookies => {}, :env => {}) } 12 | let(:app) { 13 | lambda do 14 | [200, {}, ["Hello."]] 15 | end 16 | } 17 | 18 | before do 19 | OmniAuth.config.test_mode = true 20 | end 21 | 22 | after do 23 | OmniAuth.config.test_mode = false 24 | end 25 | 26 | describe 'static configuration' do 27 | let(:options) { @options || {} } 28 | subject do 29 | OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant'}.merge(options)) 30 | end 31 | 32 | describe '#client' do 33 | it 'has correct authorize url' do 34 | allow(subject).to receive(:request) { request } 35 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize') 36 | end 37 | 38 | it 'has correct authorize params' do 39 | allow(subject).to receive(:request) { request } 40 | subject.client 41 | expect(subject.authorize_params[:domain_hint]).to be_nil 42 | end 43 | 44 | it 'has correct token url' do 45 | allow(subject).to receive(:request) { request } 46 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token') 47 | end 48 | 49 | describe "overrides" do 50 | it 'should override domain_hint' do 51 | @options = {domain_hint: 'hint'} 52 | allow(subject).to receive(:request) { request } 53 | subject.client 54 | expect(subject.authorize_params[:domain_hint]).to eql('hint') 55 | end 56 | end 57 | end 58 | 59 | end 60 | 61 | describe 'static configuration - german' do 62 | let(:options) { @options || {} } 63 | subject do 64 | OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret', tenant_id: 'tenant', base_azure_url: 'https://login.microsoftonline.de'}.merge(options)) 65 | end 66 | 67 | describe '#client' do 68 | it 'has correct authorize url' do 69 | allow(subject).to receive(:request) { request } 70 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize') 71 | end 72 | 73 | it 'has correct authorize params' do 74 | allow(subject).to receive(:request) { request } 75 | subject.client 76 | expect(subject.authorize_params[:domain_hint]).to be_nil 77 | end 78 | 79 | it 'has correct token url' do 80 | allow(subject).to receive(:request) { request } 81 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token') 82 | end 83 | 84 | it 'has correct token params' do 85 | allow(subject).to receive(:request) { request } 86 | subject.client 87 | expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000') 88 | end 89 | 90 | describe "overrides" do 91 | it 'should override domain_hint' do 92 | @options = {domain_hint: 'hint'} 93 | allow(subject).to receive(:request) { request } 94 | subject.client 95 | expect(subject.authorize_params[:domain_hint]).to eql('hint') 96 | end 97 | end 98 | end 99 | end 100 | 101 | describe 'static common configuration' do 102 | let(:options) { @options || {} } 103 | subject do 104 | OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'}.merge(options)) 105 | end 106 | 107 | before do 108 | allow(subject).to receive(:request) { request } 109 | end 110 | 111 | describe '#client' do 112 | it 'has correct authorize url' do 113 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize') 114 | end 115 | 116 | it 'has correct token url' do 117 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token') 118 | end 119 | end 120 | end 121 | 122 | describe 'dynamic configuration' do 123 | let(:provider_klass) { 124 | Class.new { 125 | def initialize(strategy) 126 | end 127 | 128 | def client_id 129 | 'id' 130 | end 131 | 132 | def client_secret 133 | 'secret' 134 | end 135 | 136 | def tenant_id 137 | 'tenant' 138 | end 139 | 140 | def authorize_params 141 | { custom_option: 'value' } 142 | end 143 | } 144 | } 145 | 146 | subject do 147 | OmniAuth::Strategies::AzureOauth2.new(app, provider_klass) 148 | end 149 | 150 | before do 151 | allow(subject).to receive(:request) { request } 152 | end 153 | 154 | describe '#client' do 155 | it 'has correct authorize url' do 156 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/authorize') 157 | end 158 | 159 | it 'has correct authorize params' do 160 | subject.client 161 | expect(subject.authorize_params[:domain_hint]).to be_nil 162 | expect(subject.authorize_params[:custom_option]).to eql('value') 163 | end 164 | 165 | it 'has correct token url' do 166 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/tenant/oauth2/token') 167 | end 168 | 169 | it 'has correct token params' do 170 | subject.client 171 | expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000') 172 | end 173 | 174 | # todo: how to get this working? 175 | # describe "overrides" do 176 | # it 'should override domain_hint' do 177 | # provider_klass.domain_hint = 'hint' 178 | # subject.client 179 | # expect(subject.authorize_params[:domain_hint]).to eql('hint') 180 | # end 181 | # end 182 | end 183 | 184 | end 185 | 186 | describe 'dynamic configuration - german' do 187 | let(:provider_klass) { 188 | Class.new { 189 | def initialize(strategy) 190 | end 191 | 192 | def client_id 193 | 'id' 194 | end 195 | 196 | def client_secret 197 | 'secret' 198 | end 199 | 200 | def tenant_id 201 | 'tenant' 202 | end 203 | 204 | def base_azure_url 205 | 'https://login.microsoftonline.de' 206 | end 207 | } 208 | } 209 | 210 | subject do 211 | OmniAuth::Strategies::AzureOauth2.new(app, provider_klass) 212 | end 213 | 214 | before do 215 | allow(subject).to receive(:request) { request } 216 | end 217 | 218 | describe '#client' do 219 | it 'has correct authorize url' do 220 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/authorize') 221 | end 222 | 223 | it 'has correct authorize params' do 224 | subject.client 225 | expect(subject.authorize_params[:domain_hint]).to be_nil 226 | end 227 | 228 | it 'has correct token url' do 229 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.de/tenant/oauth2/token') 230 | end 231 | 232 | it 'has correct token params' do 233 | subject.client 234 | expect(subject.token_params[:resource]).to eql('00000002-0000-0000-c000-000000000000') 235 | end 236 | 237 | # todo: how to get this working? 238 | # describe "overrides" do 239 | # it 'should override domain_hint' do 240 | # provider_klass.domain_hint = 'hint' 241 | # subject.client 242 | # expect(subject.authorize_params[:domain_hint]).to eql('hint') 243 | # end 244 | # end 245 | end 246 | 247 | end 248 | 249 | describe 'dynamic common configuration' do 250 | let(:provider_klass) { 251 | Class.new { 252 | def initialize(strategy) 253 | end 254 | 255 | def client_id 256 | 'id' 257 | end 258 | 259 | def client_secret 260 | 'secret' 261 | end 262 | } 263 | } 264 | 265 | subject do 266 | OmniAuth::Strategies::AzureOauth2.new(app, provider_klass) 267 | end 268 | 269 | before do 270 | allow(subject).to receive(:request) { request } 271 | end 272 | 273 | describe '#client' do 274 | it 'has correct authorize url' do 275 | expect(subject.client.options[:authorize_url]).to eql('https://login.microsoftonline.com/common/oauth2/authorize') 276 | end 277 | 278 | it 'has correct token url' do 279 | expect(subject.client.options[:token_url]).to eql('https://login.microsoftonline.com/common/oauth2/token') 280 | end 281 | end 282 | end 283 | 284 | describe "raw_info" do 285 | subject do 286 | OmniAuth::Strategies::AzureOauth2.new(app, {client_id: 'id', client_secret: 'secret'}) 287 | end 288 | 289 | let(:token) do 290 | JWT.encode({"some" => "payload"}, "secret") 291 | end 292 | 293 | let(:access_token) do 294 | double(:token => token) 295 | end 296 | 297 | before do 298 | allow(subject).to receive(:access_token) { access_token } 299 | allow(subject).to receive(:request) { request } 300 | end 301 | 302 | it "does not clash if JWT strategy is used" do 303 | expect do 304 | subject.info 305 | end.to_not raise_error 306 | end 307 | end 308 | 309 | describe 'token_params' do 310 | let(:strategy) { OmniAuth::Strategies::AzureOauth2.new(app, client_id: 'id', client_secret: 'secret') } 311 | let(:request) { double('Request', env: env) } 312 | let(:env) { {} } 313 | 314 | subject { strategy.token_params } 315 | 316 | before { allow(strategy).to receive(:request).and_return request } 317 | 318 | it { is_expected.to be_a OmniAuth::Strategy::Options } 319 | it 'has default resource' do 320 | expect(subject.resource).to eq '00000002-0000-0000-c000-000000000000' 321 | end 322 | 323 | context 'when custom crm url' do 324 | let(:crm_url) { 'https://mydomain.crm.dynamics.com/' } 325 | let(:env) { { 'omniauth.params' => { 'azure_resource' => crm_url } } } 326 | 327 | it 'has resource from url params' do 328 | expect(subject.resource).to eq crm_url 329 | end 330 | end 331 | end 332 | end 333 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require File.join('bundler', 'setup') 2 | require 'rspec' --------------------------------------------------------------------------------