omniauth-auth0-3.1.0/0000755000004100000410000000000014350575705014421 5ustar www-datawww-dataomniauth-auth0-3.1.0/Gemfile.lock0000644000004100000410000001002414350575705016640 0ustar www-datawww-dataPATH remote: . specs: omniauth-auth0 (3.1.0) omniauth (~> 2) omniauth-oauth2 (~> 1) GEM remote: https://rubygems.org/ specs: addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) ast (2.4.2) coderay (1.1.3) crack (0.4.5) rexml daemons (1.4.1) diff-lcs (1.5.0) docile (1.4.0) dotenv (2.8.1) eventmachine (1.2.7) faraday (2.7.1) faraday-net_http (>= 2.0, < 3.1) ruby2_keywords (>= 0.0.4) faraday-net_http (3.0.2) ffi (1.15.5) formatador (1.1.0) gem-release (2.2.2) guard (2.18.0) formatador (>= 0.2.4) listen (>= 2.7, < 4.0) lumberjack (>= 1.0.12, < 2.0) nenv (~> 0.1) notiffany (~> 0.0) pry (>= 0.13.0) shellany (~> 0.0) thor (>= 0.18.1) guard-compat (1.2.1) guard-rspec (4.7.3) guard (~> 2.1) guard-compat (~> 1.1) rspec (>= 2.99.0, < 4.0) hashdiff (1.0.1) hashie (5.0.0) json (2.6.3) jwt (2.5.0) listen (3.7.1) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) lumberjack (1.2.8) method_source (1.0.0) multi_json (1.15.0) multi_xml (0.6.0) mustermann (2.0.2) ruby2_keywords (~> 0.0.1) nenv (0.3.0) notiffany (0.1.3) nenv (~> 0.1) shellany (~> 0.0) oauth2 (2.0.9) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) multi_xml (~> 0.5) rack (>= 1.2, < 4) snaky_hash (~> 2.0) version_gem (~> 1.1) omniauth (2.1.0) hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection omniauth-oauth2 (1.8.0) oauth2 (>= 1.4, < 3) omniauth (~> 2.0) parallel (1.22.1) parser (3.1.3.0) ast (~> 2.4.1) pry (0.14.1) coderay (~> 1.1) method_source (~> 1.0) public_suffix (5.0.0) rack (2.2.4) rack-protection (2.2.3) rack rack-test (2.0.2) rack (>= 1.3) rainbow (3.1.1) rake (13.0.6) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) regexp_parser (2.6.1) rexml (3.2.5) rspec (3.12.0) rspec-core (~> 3.12.0) rspec-expectations (~> 3.12.0) rspec-mocks (~> 3.12.0) rspec-core (3.12.0) rspec-support (~> 3.12.0) rspec-expectations (3.12.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-mocks (3.12.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.12.0) rspec-support (3.12.0) rubocop (1.39.0) json (~> 2.3) parallel (~> 1.10) parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.23.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.24.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) shellany (0.0.1) shotgun (0.9.2) rack (>= 1.0) simplecov (0.21.2) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-cobertura (2.1.0) rexml simplecov (~> 0.19) simplecov-html (0.12.3) simplecov_json_formatter (0.1.4) sinatra (2.2.3) mustermann (~> 2.0) rack (~> 2.2) rack-protection (= 2.2.3) tilt (~> 2.0) snaky_hash (2.0.1) hashie version_gem (~> 1.1, >= 1.1.1) thin (1.8.1) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0, >= 1.0.4) rack (>= 1, < 3) thor (1.2.1) tilt (2.0.11) unicode-display_width (2.3.0) version_gem (1.1.1) webmock (3.18.1) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) PLATFORMS arm64-darwin-21 x86_64-darwin-20 x86_64-darwin-21 x86_64-linux DEPENDENCIES bundler dotenv (~> 2) gem-release (~> 2) guard-rspec (~> 4) jwt (~> 2) listen (~> 3) multi_json (~> 1) omniauth-auth0! pry (~> 0) rack-test (~> 2) rake (~> 13) rspec (~> 3) rubocop (~> 1) shotgun (~> 0) simplecov-cobertura (~> 2) sinatra (~> 2) thin (~> 1) webmock (~> 3) BUNDLED WITH 2.3.7 omniauth-auth0-3.1.0/.devcontainer/0000755000004100000410000000000014350575705017160 5ustar www-datawww-dataomniauth-auth0-3.1.0/.devcontainer/devcontainer.json0000644000004100000410000000103514350575705022533 0ustar www-datawww-data{ "name": "Ruby", "image": "mcr.microsoft.com/devcontainers/ruby:3.1", "features": { "ghcr.io/devcontainers/features/node:1": { "version": "lts" } }, // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], // Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "ruby --version", // Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. "remoteUser": "vscode" } omniauth-auth0-3.1.0/.rspec0000644000004100000410000000005714350575705015540 0ustar www-datawww-data--color --require spec_helper --format=progressomniauth-auth0-3.1.0/README.md0000644000004100000410000001352414350575705015705 0ustar www-datawww-data![Omniauth-auth0](https://cdn.auth0.com/website/sdks/banners/omniauth-auth0-banner.png) [![CircleCI](https://img.shields.io/circleci/project/github/auth0/omniauth-auth0/master.svg)](https://circleci.com/gh/auth0/omniauth-auth0) [![codecov](https://codecov.io/gh/auth0/omniauth-auth0/branch/master/graph/badge.svg)](https://codecov.io/gh/auth0/omniauth-auth0) [![Gem Version](https://badge.fury.io/rb/omniauth-auth0.svg)](https://badge.fury.io/rb/omniauth-auth0) [![MIT licensed](https://img.shields.io/dub/l/vibe-d.svg?style=flat)](https://github.com/auth0/omniauth-auth0/blob/master/LICENSE)
📚 Documentation - 🚀 Getting started - 💻 API reference - 💬 Feedback
## Documentation - [Ruby on Rails Quickstart](https://auth0.com/docs/quickstart/webapp/rails) - [Sample projects](https://github.com/auth0-samples/auth0-rubyonrails-sample) - [API Reference](https://www.rubydoc.info/gems/omniauth-auth0) ## Getting started ### Installation Add the following line to your `Gemfile`: ```ruby gem 'omniauth-auth0' ``` If you're using this strategy with Rails, also add the following for CSRF protection: ```ruby gem 'omniauth-rails_csrf_protection' ``` Then install: ```bash $ bundle install ``` See our [contributing guide](CONTRIBUTING.md) for information on local installation for development. ## Configure the SDK Adding the SDK to your Rails app requires a few steps: - [Create the configuration file](#create-the-configuration-file) - [Create the initializer](#create-the-initializer) - [Create the callback controller](#create-the-callback-controller) - [Add routes](#add-routes) ### Create the configuration file Create the file `./config/auth0.yml` within your application directory with the following content: ```yml development: auth0_domain: auth0_client_id: auth0_client_secret: ``` ### Create the initializer Create a new Ruby file in `./config/initializers/auth0.rb` to configure the OmniAuth middleware: ```ruby AUTH0_CONFIG = Rails.application.config_for(:auth0) Rails.application.config.middleware.use OmniAuth::Builder do provider( :auth0, AUTH0_CONFIG['auth0_client_id'], AUTH0_CONFIG['auth0_client_secret'], AUTH0_CONFIG['auth0_domain'], callback_path: '/auth/auth0/callback', authorize_params: { scope: 'openid profile' } ) end ``` ### Create the callback controller Create a new controller `./app/controllers/auth0_controller.rb` to handle the callback from Auth0. > You can also run `rails generate controller auth0 callback failure logout --skip-assets --skip-helper --skip-routes --skip-template-engine` to scaffold this controller for you. ```ruby # ./app/controllers/auth0_controller.rb class Auth0Controller < ApplicationController def callback # OmniAuth stores the information returned from Auth0 and the IdP in request.env['omniauth.auth']. # In this code, you will pull the raw_info supplied from the id_token and assign it to the session. # Refer to https://github.com/auth0/omniauth-auth0/blob/master/EXAMPLES.md#example-of-the-resulting-authentication-hash for complete information on 'omniauth.auth' contents. auth_info = request.env['omniauth.auth'] session[:userinfo] = auth_info['extra']['raw_info'] # Redirect to the URL you want after successful auth redirect_to '/dashboard' end def failure # Handles failed authentication -- Show a failure page (you can also handle with a redirect) @error_msg = request.params['message'] end def logout # you will finish this in a later step end end ``` ### Add routes Finally, add the following routes to your `./config/routes.rb` file: ```ruby Rails.application.routes.draw do # .. get '/auth/auth0/callback' => 'auth0#callback' get '/auth/failure' => 'auth0#failure' get '/auth/logout' => 'auth0#logout' end ``` ## Logging in To redirect your users to Auth0 for authentication, redirect your users to the `/auth/auth0` endpoint of your app. One way to do this is to use a link or button on a page: ```html <%= button_to 'Login', '/auth/auth0', method: :post %> ``` ## Feedback ### Contributing We appreciate feedback and contribution to this repo! Before you get started, please see the following: - [Auth0's general contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) - [Auth0's code of conduct guidelines](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md) - [This repo's contribution guide](https://github.com/auth0/omniauth-auth0/blob/master/CONTRIBUTING.md) ### Raise an issue To provide feedback or report a bug, please [raise an issue on our issue tracker](https://github.com/auth0/omniauth-auth0/issues). ### Vulnerability Reporting Please do not report security vulnerabilities on the public GitHub issue tracker. The [Responsible Disclosure Program](https://auth0.com/whitehat) details the procedure for disclosing security issues. ---

Auth0 Logo

Auth0 is an easy to implement, adaptable authentication and authorization platform. To learn more checkout Why Auth0?

This project is licensed under the MIT license. See the LICENSE file for more info.

omniauth-auth0-3.1.0/.circleci/0000755000004100000410000000000014350575705016254 5ustar www-datawww-dataomniauth-auth0-3.1.0/.circleci/config.yml0000644000004100000410000000272514350575705020252 0ustar www-datawww-dataversion: 2.1 orbs: ship: auth0/ship@0 codecov: codecov/codecov@3 matrix_rubyversions: &matrix_rubyversions matrix: parameters: rubyversion: ["2.7", "3.0", "3.1"] # Default version of ruby to use for lint and publishing default_rubyversion: &default_rubyversion "2.7" executors: ruby: parameters: rubyversion: type: string default: *default_rubyversion docker: - image: cimg/ruby:<< parameters.rubyversion >> jobs: run-tests: parameters: rubyversion: type: string default: *default_rubyversion executor: name: ruby rubyversion: "<< parameters.rubyversion >>" steps: - checkout - restore_cache: keys: - gems-v2-{{ checksum "Gemfile" }} - gems-v2- - run: | echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV source $BASH_ENV gem install bundler bundle check || bundle install - save_cache: key: gems-v2--{{ checksum "Gemfile" }} paths: - vendor/bundle - run: bundle exec rake spec - codecov/upload workflows: tests: jobs: - run-tests: <<: *matrix_rubyversions - ship/ruby-publish: context: - publish-rubygems - publish-gh filters: branches: only: - master requires: - run-tests omniauth-auth0-3.1.0/spec/0000755000004100000410000000000014350575705015353 5ustar www-datawww-dataomniauth-auth0-3.1.0/spec/omniauth/0000755000004100000410000000000014350575705017177 5ustar www-datawww-dataomniauth-auth0-3.1.0/spec/omniauth/strategies/0000755000004100000410000000000014350575705021351 5ustar www-datawww-dataomniauth-auth0-3.1.0/spec/omniauth/strategies/auth0_spec.rb0000644000004100000410000003526414350575705023743 0ustar www-datawww-data# frozen_string_literal: true require 'spec_helper' require 'jwt' require 'multi_json' OmniAuth.config.allowed_request_methods = [:get, :post] RSpec.shared_examples 'site has valid domain url' do |url| it { expect(subject.site).to eq(url) } end describe OmniAuth::Strategies::Auth0 do let(:client_id) { 'CLIENT_ID' } let(:client_secret) { 'CLIENT_SECRET' } let(:domain_url) { 'https://samples.auth0.com' } let(:application) do lambda do [200, {}, ['Hello.']] end end let(:auth0) do OmniAuth::Strategies::Auth0.new( application, client_id, client_secret, domain_url ) end describe 'client_options' do let(:subject) { OmniAuth::Strategies::Auth0.new( application, client_id, client_secret, domain_url ).client } context 'domain with https' do let(:domain_url) { 'https://samples.auth0.com' } it_behaves_like 'site has valid domain url', 'https://samples.auth0.com' end context 'domain with http' do let(:domain_url) { 'http://mydomain.com' } it_behaves_like 'site has valid domain url', 'http://mydomain.com' end context 'domain with host only' do let(:domain_url) { 'samples.auth0.com' } it_behaves_like 'site has valid domain url', 'https://samples.auth0.com' end it 'should have correct authorize path' do expect(subject.options[:authorize_url]).to eq('/authorize') end it 'should have the correct userinfo path' do expect(subject.options[:userinfo_url]).to eq('/userinfo') end it 'should have the correct token path' do expect(subject.options[:token_url]).to eq('/oauth/token') end end describe 'options' do let(:subject) { auth0.options } it 'should have the correct client_id' do expect(subject[:client_id]).to eq(client_id) end it 'should have the correct client secret' do expect(subject[:client_secret]).to eq(client_secret) end it 'should have correct domain' do expect(subject[:domain]).to eq(domain_url) end end describe 'oauth' do it 'redirects to hosted login page' do get 'auth/auth0' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection') expect(redirect_url).not_to have_query('connection_scope') expect(redirect_url).not_to have_query('prompt') expect(redirect_url).not_to have_query('screen_hint') expect(redirect_url).not_to have_query('login_hint') expect(redirect_url).not_to have_query('organization') expect(redirect_url).not_to have_query('invitation') end it 'redirects to hosted login page' do get 'auth/auth0?connection=abcd' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).to have_query('connection', 'abcd') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection_scope') expect(redirect_url).not_to have_query('prompt') expect(redirect_url).not_to have_query('screen_hint') expect(redirect_url).not_to have_query('login_hint') expect(redirect_url).not_to have_query('organization') expect(redirect_url).not_to have_query('invitation') end it 'redirects to the hosted login page with connection_scope' do get 'auth/auth0?connection_scope=identity_provider_scope' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url) .to have_query('connection_scope', 'identity_provider_scope') end it 'redirects to hosted login page with prompt=login' do get 'auth/auth0?prompt=login' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).to have_query('prompt', 'login') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection') expect(redirect_url).not_to have_query('login_hint') expect(redirect_url).not_to have_query('organization') expect(redirect_url).not_to have_query('invitation') end it 'redirects to hosted login page with screen_hint=signup' do get 'auth/auth0?screen_hint=signup' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).to have_query('screen_hint', 'signup') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection') expect(redirect_url).not_to have_query('login_hint') expect(redirect_url).not_to have_query('organization') expect(redirect_url).not_to have_query('invitation') end it 'redirects to hosted login page with organization=TestOrg and invitation=TestInvite' do get 'auth/auth0?organization=TestOrg&invitation=TestInvite' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).to have_query('organization', 'TestOrg') expect(redirect_url).to have_query('invitation', 'TestInvite') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection') expect(redirect_url).not_to have_query('connection_scope') expect(redirect_url).not_to have_query('prompt') expect(redirect_url).not_to have_query('screen_hint') expect(redirect_url).not_to have_query('login_hint') end it 'redirects to hosted login page with login_hint=example@mail.com' do get 'auth/auth0?login_hint=example@mail.com' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to start_with('https://samples.auth0.com/authorize') expect(redirect_url).to have_query('response_type', 'code') expect(redirect_url).to have_query('state') expect(redirect_url).to have_query('client_id') expect(redirect_url).to have_query('redirect_uri') expect(redirect_url).to have_query('login_hint', 'example@mail.com') expect(redirect_url).not_to have_query('auth0Client') expect(redirect_url).not_to have_query('connection') expect(redirect_url).not_to have_query('connection_scope') expect(redirect_url).not_to have_query('prompt') expect(redirect_url).not_to have_query('screen_hint') expect(redirect_url).not_to have_query('organization') expect(redirect_url).not_to have_query('invitation') end def session session_cookie = last_response.cookies['rack.session'].first session_data, _, _ = session_cookie.rpartition('--') decoded_session_data = Base64.decode64(session_data) Marshal.load(decoded_session_data) end it "stores session['authorize_params'] as a plain Ruby Hash" do get '/auth/auth0' expect(session['authorize_params'].class).to eq(::Hash) end describe 'callback' do let(:access_token) { 'access token' } let(:expires_in) { 2000 } let(:token_type) { 'bearer' } let(:refresh_token) { 'refresh token' } let(:telemetry_value) { Class.new.extend(OmniAuth::Auth0::Telemetry).telemetry_encoded } let(:user_id) { 'user identifier' } let(:state) { SecureRandom.hex(8) } let(:name) { 'John' } let(:nickname) { 'J' } let(:picture) { 'some picture url' } let(:email) { 'mail@mail.com' } let(:email_verified) { true } let(:id_token) do payload = {} payload['sub'] = user_id payload['iss'] = "#{domain_url}/" payload['aud'] = client_id payload['name'] = name payload['nickname'] = nickname payload['picture'] = picture payload['email'] = email payload['email_verified'] = email_verified JWT.encode payload, client_secret, 'HS256' end let(:oauth_response) do { access_token: access_token, expires_in: expires_in, token_type: token_type } end let(:oidc_response) do { id_token: id_token, access_token: access_token, expires_in: expires_in, token_type: token_type } end let(:basic_user_info) { { "sub" => user_id, "name" => name } } def stub_auth(body) stub_request(:post, 'https://samples.auth0.com/oauth/token') .with(headers: { 'Auth0-Client' => telemetry_value }) .to_return( headers: { 'Content-Type' => 'application/json' }, body: MultiJson.encode(body) ) end def stub_userinfo(body) stub_request(:get, 'https://samples.auth0.com/userinfo') .to_return( headers: { 'Content-Type' => 'application/json' }, body: MultiJson.encode(body) ) end def trigger_callback get '/auth/auth0/callback', { 'state' => state }, 'rack.session' => { 'omniauth.state' => state } end before(:each) do WebMock.reset! end let(:subject) do MultiJson.decode(last_response.body) end context 'basic oauth' do before do stub_auth(oauth_response) stub_userinfo(basic_user_info) trigger_callback end it 'to succeed' do expect(last_response.status).to eq(200) end it 'has credentials' do expect(subject['credentials']['token']).to eq(access_token) expect(subject['credentials']['expires']).to be true expect(subject['credentials']['expires_at']).to_not be_nil end it 'has basic values' do expect(subject['provider']).to eq('auth0') expect(subject['uid']).to eq(user_id) expect(subject['info']['name']).to eq(name) end it 'should use the user info endpoint' do expect(subject['extra']['raw_info']).to eq(basic_user_info) end end context 'basic oauth w/refresh token' do before do stub_auth(oauth_response.merge(refresh_token: refresh_token)) stub_userinfo(basic_user_info) trigger_callback end it 'to succeed' do expect(last_response.status).to eq(200) end it 'has credentials' do expect(subject['credentials']['token']).to eq(access_token) expect(subject['credentials']['refresh_token']).to eq(refresh_token) expect(subject['credentials']['expires']).to be true expect(subject['credentials']['expires_at']).to_not be_nil end end context 'oidc' do before do stub_auth(oidc_response) trigger_callback end it 'to succeed' do expect(last_response.status).to eq(200) end it 'has credentials' do expect(subject['credentials']['token']).to eq(access_token) expect(subject['credentials']['expires']).to be true expect(subject['credentials']['expires_at']).to_not be_nil expect(subject['credentials']['id_token']).to eq(id_token) end it 'has basic values' do expect(subject['provider']).to eq('auth0') expect(subject['uid']).to eq(user_id) end it 'has info' do expect(subject['info']['name']).to eq(name) expect(subject['info']['nickname']).to eq(nickname) expect(subject['info']['image']).to eq(picture) expect(subject['info']['email']).to eq(email) end it 'has extra' do expect(subject['extra']['raw_info']['email_verified']).to be true end end end end describe 'error_handling' do it 'fails when missing client_id' do @app = make_application(client_id: nil) get 'auth/auth0' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to fail_auth_with('missing_client_id') end it 'fails when missing client_secret' do @app = make_application(client_secret: nil) get 'auth/auth0' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to fail_auth_with('missing_client_secret') end it 'fails when missing domain' do @app = make_application(domain: nil) get 'auth/auth0' expect(last_response.status).to eq(302) redirect_url = last_response.headers['Location'] expect(redirect_url).to fail_auth_with('missing_domain') end end end RSpec::Matchers.define :fail_auth_with do |message| match do |actual| uri = URI(actual) query = CGI.parse(uri.query) (uri.path == '/auth/failure') && (query['message'] == [message]) && (query['strategy'] == ['auth0']) end end RSpec::Matchers.define :have_query do |key, value| match do |actual| uri = redirect_uri(actual) query = query(uri) if value.nil? query.key?(key) else query[key] == [value] end end def redirect_uri(string) URI(string) end def query(uri) CGI.parse(uri.query) end end omniauth-auth0-3.1.0/spec/omniauth/auth0/0000755000004100000410000000000014350575705020220 5ustar www-datawww-dataomniauth-auth0-3.1.0/spec/omniauth/auth0/telemetry_spec.rb0000644000004100000410000000142014350575705023566 0ustar www-datawww-datarequire 'spec_helper' require 'json' describe OmniAuth::Auth0::Telemetry do let(:test_class) { Class.new.extend(OmniAuth::Auth0::Telemetry) } describe 'telemetry' do it 'should have the correct SDK name' do expect(test_class.telemetry).to have_key(:name) expect(test_class.telemetry[:name]).to eq('omniauth-auth0') end it 'should have the correct SDK version' do expect(test_class.telemetry).to have_key(:version) expect(test_class.telemetry[:version]).to eq(OmniAuth::Auth0::VERSION) end it 'should include the Ruby version' do expect(test_class.telemetry).to have_key(:env) expect(test_class.telemetry[:env]).to have_key(:ruby) expect(test_class.telemetry[:env][:ruby]).to eq(RUBY_VERSION) end end end omniauth-auth0-3.1.0/spec/omniauth/auth0/jwt_validator_spec.rb0000644000004100000410000005470514350575705024443 0ustar www-datawww-datarequire 'spec_helper' require 'json' require 'jwt' describe OmniAuth::Auth0::JWTValidator do # # Reused data # let(:client_id) { 'CLIENT_ID' } let(:client_secret) { 'CLIENT_SECRET' } let(:domain) { 'samples.auth0.com' } let(:future_timecode) { 32_503_680_000 } let(:past_timecode) { 303_912_000 } let(:valid_jwks_kid) { 'NkJCQzIyQzRBMEU4NjhGNUU4MzU4RkY0M0ZDQzkwOUQ0Q0VGNUMwQg' } let(:rsa_private_key) do OpenSSL::PKey::RSA.generate 2048 end let(:valid_jwks) do { keys: [ { kid: valid_jwks_kid, x5c: [Base64.encode64(make_cert(rsa_private_key).to_der)] } ] }.to_json end let(:jwks) do current_dir = File.dirname(__FILE__) jwks_file = File.read("#{current_dir}/../../resources/jwks.json") JSON.parse(jwks_file, symbolize_names: true) end # # Specs # describe 'JWT verifier default values' do let(:jwt_validator) do make_jwt_validator end it 'should have the correct issuer' do expect(jwt_validator.issuer).to eq('https://samples.auth0.com/') end end describe 'JWT verifier token_head' do let(:jwt_validator) do make_jwt_validator end it 'should parse the head of a valid JWT' do expect(jwt_validator.token_head(make_hs256_token)[:alg]).to eq('HS256') end it 'should fail parsing the head of a blank JWT' do expect(jwt_validator.token_head('')).to eq({}) end it 'should fail parsing the head of an invalid JWT' do expect(jwt_validator.token_head('.')).to eq({}) end it 'should throw an exception for invalid JSON' do expect do jwt_validator.token_head('QXV0aDA=') end.to raise_error(JSON::ParserError) end end describe 'JWT verifier jwks_public_cert' do let(:jwt_validator) do make_jwt_validator end it 'should return a public_key' do x5c = jwks[:keys].first[:x5c].first public_cert = jwt_validator.jwks_public_cert(x5c) expect(public_cert.instance_of?(OpenSSL::PKey::RSA)).to eq(true) end it 'should fail with an invalid x5c' do expect do jwt_validator.jwks_public_cert('QXV0aDA=') end.to raise_error(OpenSSL::X509::CertificateError) end end describe 'JWT verifier jwks key parsing' do let(:jwt_validator) do make_jwt_validator end before do stub_complete_jwks end it 'should return a key' do expect(jwt_validator.jwks_key(:alg, valid_jwks_kid)).to eq('RS256') end it 'should return an x5c key' do expect(jwt_validator.jwks_key(:x5c, valid_jwks_kid).length).to eq(1) end it 'should return nil if there is not key' do expect(jwt_validator.jwks_key(:auth0, valid_jwks_kid)).to eq(nil) end it 'should return nil if the key ID is invalid' do expect(jwt_validator.jwks_key(:alg, "#{valid_jwks_kid}_invalid")).to eq(nil) end end describe 'JWT verifier custom issuer' do context 'same as domain' do let(:jwt_validator) do make_jwt_validator(opt_issuer: domain) end it 'should have the correct issuer' do expect(jwt_validator.issuer).to eq('https://samples.auth0.com/') end it 'should have the correct domain' do expect(jwt_validator.issuer).to eq('https://samples.auth0.com/') end end context 'different from domain' do shared_examples_for 'has correct issuer and domain' do let(:jwt_validator) { make_jwt_validator(opt_issuer: opt_issuer) } it 'should have the correct issuer' do expect(jwt_validator.issuer).to eq('https://different.auth0.com/') end it 'should have the correct domain' do expect(jwt_validator.domain).to eq('https://samples.auth0.com/') end end context 'without protocol and trailing slash' do let(:opt_issuer) { 'different.auth0.com' } it_behaves_like 'has correct issuer and domain' end context 'with protocol and trailing slash' do let(:opt_issuer) { 'https://different.auth0.com/' } it_behaves_like 'has correct issuer and domain' end end end describe 'JWT verifier verify' do let(:jwt_validator) do make_jwt_validator end before do stub_complete_jwks stub_expected_jwks end it 'should fail when JWT is nil' do expect do jwt_validator.verify(nil) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "ID token is required but missing" })) end it 'should fail when JWT is not well-formed' do expect do jwt_validator.verify('abc.123') end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "ID token could not be decoded" })) end it 'should fail with missing issuer' do expect do jwt_validator.verify(make_hs256_token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Issuer (iss) claim must be a string present in the ID token" })) end it 'should fail with invalid issuer' do payload = { iss: 'https://auth0.com/' } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Issuer (iss) claim mismatch in the ID token, expected (https://samples.auth0.com/), found (https://auth0.com/)" })) end it 'should fail when subject is missing' do payload = { iss: "https://#{domain}/", sub: '' } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Subject (sub) claim must be a string present in the ID token" })) end it 'should fail with missing audience' do payload = { iss: "https://#{domain}/", sub: 'sub' } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Audience (aud) claim must be a string or array of strings present in the ID token" })) end it 'should fail with invalid audience' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: 'Auth0' } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Audience (aud) claim mismatch in the ID token; expected #{client_id} but found Auth0" })) end it 'should fail when missing expiration' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Expiration time (exp) claim must be a number present in the ID token" })) end it 'should fail when past expiration' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Expiration time (exp) claim error in the ID token; current time (#{Time.now}) is after expiration time (#{Time.at(past_timecode + 60)})" })) end it 'should pass when past expiration but within default leeway' do exp = Time.now.to_i - 59 payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: exp, iat: past_timecode } token = make_hs256_token(payload) id_token = jwt_validator.verify(token) expect(id_token['exp']).to eq(exp) end it 'should fail when past expiration and outside default leeway' do exp = Time.now.to_i - 61 payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: exp, iat: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Expiration time (exp) claim error in the ID token; current time (#{Time.now}) is after expiration time (#{Time.at(exp + 60)})" })) end it 'should fail when missing iat' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Issued At (iat) claim must be a number present in the ID token" })) end it 'should fail when authorize params has nonce but nonce is missing in the token' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { nonce: 'noncey' }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Nonce (nonce) claim must be a string present in the ID token" })) end it 'should fail when authorize params has nonce but token nonce does not match' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode, nonce: 'mismatch' } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { nonce: 'noncey' }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Nonce (nonce) claim value mismatch in the ID token; expected (noncey), found (mismatch)" })) end it 'should fail when “aud” is an array of strings and azp claim is not present' do aud = [ client_id, "https://#{domain}/userinfo" ] payload = { iss: "https://#{domain}/", sub: 'sub', aud: aud, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Authorized Party (azp) claim must be a string present in the ID token when Audience (aud) claim has multiple values" })) end it 'should fail when "azp" claim doesnt match the expected aud' do aud = [ client_id, "https://#{domain}/userinfo" ] payload = { iss: "https://#{domain}/", sub: 'sub', aud: aud, exp: future_timecode, iat: past_timecode, azp: 'not_expected' } token = make_hs256_token(payload) expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Authorized Party (azp) claim mismatch in the ID token; expected (#{client_id}), found (not_expected)" })) end it 'should fail when “max_age” sent on the authentication request and this claim is not present' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { max_age: 60 }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Authentication Time (auth_time) claim must be a number present in the ID token when Max Age (max_age) is specified" })) end it 'should fail when “max_age” sent on the authentication request and this claim added the “max_age” value doesn’t represent a date in the future' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode, auth_time: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { max_age: 60 }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (#{Time.now}) is after last auth time (#{Time.at(past_timecode + 60 + 60)})" })) end it 'should fail when “max_age” sent on the authentication request and this claim added the “max_age” value doesn’t represent a date in the future, outside the default leeway' do now = Time.now.to_i auth_time = now - 121 max_age = 60 payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode, auth_time: auth_time } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { max_age: max_age }) # Time.at(auth_time + max_age + leeway end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (#{Time.now}) is after last auth time (#{Time.at(auth_time + max_age + 60)})" })) end it 'should verify when “max_age” sent on the authentication request and this claim added the “max_age” value doesn’t represent a date in the future, outside the default leeway' do now = Time.now.to_i auth_time = now - 119 max_age = 60 payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode, auth_time: auth_time } token = make_hs256_token(payload) id_token = jwt_validator.verify(token, { max_age: max_age }) expect(id_token['auth_time']).to eq(auth_time) end it 'should fail when authorize params has organization but org_id is missing in the token' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { organization: 'Test Org' }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Organization Id (org_id) claim must be a string present in the ID token" })) end it 'should fail when authorize params has organization but token org_id does not match' do payload = { iss: "https://#{domain}/", sub: 'sub', aud: client_id, exp: future_timecode, iat: past_timecode, org_id: 'Wrong Org' } token = make_hs256_token(payload) expect do jwt_validator.verify(token, { organization: 'Test Org' }) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Organization Id (org_id) claim value mismatch in the ID token; expected 'Test Org', found 'Wrong Org'" })) end it 'should fail for RS256 token when kid is incorrect' do domain = 'example.org' sub = 'abc123' payload = { sub: sub, exp: future_timecode, iss: "https://#{domain}/", iat: past_timecode, aud: client_id } invalid_kid = 'invalid-kid' token = make_rs256_token(payload, invalid_kid) expect do verified_token = make_jwt_validator(opt_domain: domain).verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Could not find a public key for Key ID (kid) 'invalid-kid'" })) end it 'should fail when RS256 token has invalid signature' do domain = 'example.org' sub = 'abc123' payload = { sub: sub, exp: future_timecode, iss: "https://#{domain}/", iat: past_timecode, aud: client_id } token = make_rs256_token(payload) + 'bad' expect do verified_token = make_jwt_validator(opt_domain: domain).verify(token) end.to raise_error(an_instance_of(JWT::VerificationError).and having_attributes({ message: "Signature verification failed" })) end it 'should fail when algorithm is not RS256 or HS256' do payload = { iss: "https://#{domain}/", sub: 'abc123', aud: client_id, exp: future_timecode, iat: past_timecode } token = JWT.encode payload, 'secret', 'HS384' expect do jwt_validator.verify(token) end.to raise_error(an_instance_of(OmniAuth::Auth0::TokenValidationError).and having_attributes({ message: "Signature algorithm of HS384 is not supported. Expected the ID token to be signed with RS256 or HS256" })) end it 'should fail when HS256 token has invalid signature' do payload = { iss: "https://#{domain}/", sub: 'abc123', aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload, 'bad_secret') expect do # validator is configured to use "CLIENT_SECRET" by default jwt_validator.verify(token) end.to raise_error(an_instance_of(JWT::VerificationError)) end it 'should verify a valid HS256 token with multiple audiences' do audience = [ client_id, "https://#{domain}/userinfo" ] payload = { iss: "https://#{domain}/", sub: 'sub', aud: audience, exp: future_timecode, iat: past_timecode, azp: client_id } token = make_hs256_token(payload) id_token = jwt_validator.verify(token) expect(id_token['aud']).to eq(audience) end it 'should verify a standard HS256 token' do sub = 'abc123' payload = { iss: "https://#{domain}/", sub: sub, aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) verified_token = jwt_validator.verify(token) expect(verified_token['sub']).to eq(sub) end it 'should verify a standard RS256 token' do domain = 'example.org' sub = 'abc123' payload = { sub: sub, exp: future_timecode, iss: "https://#{domain}/", iat: past_timecode, aud: client_id } token = make_rs256_token(payload) verified_token = make_jwt_validator(opt_domain: domain).verify(token) expect(verified_token['sub']).to eq(sub) end it 'should verify a HS256 JWT signature when calling verify signature directly' do sub = 'abc123' payload = { iss: "https://#{domain}/", sub: sub, aud: client_id, exp: future_timecode, iat: past_timecode } token = make_hs256_token(payload) verified_token_signature = jwt_validator.verify_signature(token) expect(verified_token_signature[0]).to eq('CLIENT_SECRET') expect(verified_token_signature[1]).to eq('HS256') end it 'should verify a RS256 JWT signature verify signature directly' do domain = 'example.org' sub = 'abc123' payload = { sub: sub, exp: future_timecode, iss: "https://#{domain}/", iat: past_timecode, aud: client_id } token = make_rs256_token(payload) verified_token_signature = make_jwt_validator(opt_domain: domain).verify_signature(token) expect(verified_token_signature.length).to be(2) expect(verified_token_signature[0]).to be_a(OpenSSL::PKey::RSA) expect(verified_token_signature[1]).to eq('RS256') end end private def make_jwt_validator(opt_domain: domain, opt_issuer: nil) opts = OpenStruct.new( domain: opt_domain, client_id: client_id, client_secret: client_secret ) opts[:issuer] = opt_issuer unless opt_issuer.nil? OmniAuth::Auth0::JWTValidator.new(opts) end def make_hs256_token(payload = nil, secret = nil) payload = { sub: 'abc123' } if payload.nil? secret = client_secret if secret.nil? JWT.encode payload, secret, 'HS256' end def make_rs256_token(payload = nil, kid = nil) payload = { sub: 'abc123' } if payload.nil? kid = valid_jwks_kid if kid.nil? JWT.encode payload, rsa_private_key, 'RS256', kid: kid end def make_cert(private_key) cert = OpenSSL::X509::Certificate.new cert.issuer = OpenSSL::X509::Name.parse('/C=BE/O=Auth0/OU=Auth0/CN=Auth0') cert.subject = cert.issuer cert.not_before = Time.now cert.not_after = Time.now + 365 * 24 * 60 * 60 cert.public_key = private_key.public_key cert.serial = 0x0 cert.version = 2 ef = OpenSSL::X509::ExtensionFactory.new ef.subject_certificate = cert ef.issuer_certificate = cert cert.extensions = [ ef.create_extension('basicConstraints', 'CA:TRUE', true), ef.create_extension('subjectKeyIdentifier', 'hash') ] cert.add_extension ef.create_extension( 'authorityKeyIdentifier', 'keyid:always,issuer:always' ) cert.sign private_key, OpenSSL::Digest::SHA1.new end def stub_complete_jwks stub_request(:get, 'https://samples.auth0.com/.well-known/jwks.json') .to_return( headers: { 'Content-Type' => 'application/json' }, body: jwks.to_json, status: 200 ) end def stub_expected_jwks stub_request(:get, 'https://example.org/.well-known/jwks.json') .to_return( headers: { 'Content-Type' => 'application/json' }, body: valid_jwks, status: 200 ) end end omniauth-auth0-3.1.0/spec/resources/0000755000004100000410000000000014350575705017365 5ustar www-datawww-dataomniauth-auth0-3.1.0/spec/resources/jwks.json0000644000004100000410000000637414350575705021250 0ustar www-datawww-data{ "keys": [ { "alg": "RS256", "kty": "RSA", "use": "sig", "x5c": [ "MIIDCzCCAfOgAwIBAgIJAJP6qydiMpsuMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNVBAMMEXNhbXBsZXMuYXV0aDAuY29tMB4XDTE0MDUyNjIyMDA1MFoXDTI4MDIwMjIyMDA1MFowHDEaMBgGA1UEAwwRc2FtcGxlcy5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkH4CFGSJ4s3mwCBzaGGwxa9Jxzfb1ia4nUumxbsuaB7PClZZgrNQiOR3MXVNV9W6F1D+wjT6oFHOo7TOkVI22I/ff3XZTE0F35UUHGWRtiQ4LdZxwOPTed2Lax3F2DEyl3Y0CguUKbq2sSghvHYcggM6aj3N53VBsnBh/kdrURDLx1RYqBIL6Fvkhb/V/v/u9UKhZM0CDQRef9FZ7R8q9ie9cnbDOj1dT9d64kiJIYtTraG0gOrs4LI+4KK0EZu5R7Uo053IK7kfNasWhDkl8yxNYkDxwfcIuAcDmLgLnAI4tfW5beJuw+/w75PO/EwzwsnvppXaAz7e3Wf8g1yWFAgMBAAGjUDBOMB0GA1UdDgQWBBTsmytFLNox+NUZdTNlCUL3hHrngTAfBgNVHSMEGDAWgBTsmytFLNox+NUZdTNlCUL3hHrngTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAodbRX/34LnWB70l8dpDF1neDoG29F0XdpE9ICWHeWB1gb/FvJ5UMy9/pnL0DI3mPwkTDDob+16Zc68o6dT6sH3vEUP1iRreJlFADEmJZjrH9P4Y7ttx3G2Uw2RU5uucXIqiyMDBrQo4vx4Lnghl+b/WYbZJgzLfZLgkOEjcznS0Yi5Wdz6MvaL3FehSfweHyrjmxz0e8elHq7VY8OqRA+4PmUBce9BgDCk9fZFjgj8l0m9Vc5pPKSY9LMmTyrYkeDr/KppqdXKOCHmv7AIGb6rMCtbkIL/CM7Bh9Hx78/UKAz87Sl9A1yXVNjKbZwOEW60ORIwJmd8Tv46gJF+/rV" ], "n": "pB-AhRkieLN5sAgc2hhsMWvScc329YmuJ1LpsW7LmgezwpWWYKzUIjkdzF1TVfVuhdQ_sI0-qBRzqO0zpFSNtiP33912UxNBd-VFBxlkbYkOC3WccDj03ndi2sdxdgxMpd2NAoLlCm6trEoIbx2HIIDOmo9zed1QbJwYf5Ha1EQy8dUWKgSC-hb5IW_1f7_7vVCoWTNAg0EXn_RWe0fKvYnvXJ2wzo9XU_XeuJIiSGLU62htIDq7OCyPuCitBGbuUe1KNOdyCu5HzWrFoQ5JfMsTWJA8cH3CLgHA5i4C5wCOLX1uW3ibsPv8O-TzvxMM8LJ76aV2gM-3t1n_INclhQ", "e": "AQAB", "kid": "NkJCQzIyQzRBMEU4NjhGNUU4MzU4RkY0M0ZDQzkwOUQ0Q0VGNUMwQg", "x5t": "NkJCQzIyQzRBMEU4NjhGNUU4MzU4RkY0M0ZDQzkwOUQ0Q0VGNUMwQg" }, { "alg": "RS256", "kty": "RSA", "use": "sig", "x5c": [ "MIIC8DCCAdigAwIBAgIJ4pL5sRgcIYGZMA0GCSqGSIb3DQEBBQUAMB8xHTAbBgNVBAMTFGxiYWxtYWNlZGEuYXV0aDAuY29tMB4XDTE1MTIxMjE5MDczM1oXDTI5MDgyMDE5MDczM1owHzEdMBsGA1UEAxMUbGJhbG1hY2VkYS5hdXRoMC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPoo5DA/X8suAZujdmD2D88Ggtu8G/kuLUdEuj1W3+wzmFcEqQpE532rg8L0uppWKAbmLWzkuwyioNDhWwCtXnug3BFQf5Lrc6nTxjk4ZQt/HdsYWCGSSZueMUG/3I+2PSql3atD2nedjY6Z9hWU8kzOjF9wzkLMgPf/OYpuz9A+6d+/K8jApRPfsQ1LDVWDG8YRtj+IyHhSvXS+cK03iuD7yVLKkIZuoS8ymMJpnZONHGds/3P9pHY29KqliSYW0eGEX3BIarZG06gRJ+88WUbRi9+rfVAoGLq++S+bc021txK+qYS3nknhY0uv/ODBb4eeycuDjjdyLBCShVvbXFAgMBAAGjLzAtMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFG38TTjyzhRmpK7MXfvBXDcBtYJ3MA0GCSqGSIb3DQEBBQUAA4IBAQCLNW+rA25tjHs6Sa9VPgBfMMLd1PIEgMpQhET9JqpGYUgB+0q1leXw1cwh14x/6PF2oo3jPOMW+wCDA7KAVKYewYSr/Enph+zNFPaq2YQL9dCsVFcBsnEGznwZaqHrqxQDX9S2Ek6E9jNsuBCSpAPcTsfbn2TXz77V+HZ/4tbwRvYEX1S5agiZFyjZzJMiZU1KQzP5PhfzD6RPl5KTK2PYRhVdXwyuFxOdJzCzOC9E/Uw30Zd6+9oHmoNfvJr8BRy67YWjXaQAh2m8e+zv/dEzPimgvaLmI1yz4W+93dJy3NdMuCvObOqA534tviv5PkV57ewXAnWPbxyBHr57HdQ1" ], "n": "z6KOQwP1_LLgGbo3Zg9g_PBoLbvBv5Li1HRLo9Vt_sM5hXBKkKROd9q4PC9LqaVigG5i1s5LsMoqDQ4VsArV57oNwRUH-S63Op08Y5OGULfx3bGFghkkmbnjFBv9yPtj0qpd2rQ9p3nY2OmfYVlPJMzoxfcM5CzID3_zmKbs_QPunfvyvIwKUT37ENSw1VgxvGEbY_iMh4Ur10vnCtN4rg-8lSypCGbqEvMpjCaZ2TjRxnbP9z_aR2NvSqpYkmFtHhhF9wSGq2RtOoESfvPFlG0Yvfq31QKBi6vvkvm3NNtbcSvqmEt55J4WNLr_zgwW-HnsnLg443ciwQkoVb21xQ", "e": "AQAB", "kid": "RUVBOTVEMEZBMTA5NDAzNEQzNTZGNzMyMTI4MzU1RkNFQzhCQTM0Mg", "x5t": "RUVBOTVEMEZBMTA5NDAzNEQzNTZGNzMyMTI4MzU1RkNFQzhCQTM0Mg" } ] }omniauth-auth0-3.1.0/spec/spec_helper.rb0000644000004100000410000000277214350575705020201 0ustar www-datawww-data$LOAD_PATH.unshift File.expand_path(__dir__) $LOAD_PATH.unshift File.expand_path('../lib', __dir__) require 'multi_json' require 'simplecov' SimpleCov.start if ENV['CI'] == 'true' require 'simplecov-cobertura' SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter end require 'rspec' require 'rack/test' require 'webmock/rspec' require 'omniauth' require 'omniauth-auth0' require 'sinatra' WebMock.disable_net_connect! RSpec.configure do |config| config.include WebMock::API config.include Rack::Test::Methods config.extend OmniAuth::Test::StrategyMacros, type: :strategy config.filter_run focus: true config.run_all_when_everything_filtered = true def app @app || make_application end def make_application(options = {}) client_id = 'CLIENT_ID' secret = 'CLIENT_SECRET' domain = 'samples.auth0.com' client_id = options.delete(:client_id) if options.key?(:client_id) secret = options.delete(:client_secret) if options.key?(:client_secret) domain = options.delete(:domain) if options.key?(:domain) Sinatra.new do configure do enable :sessions set :show_exceptions, false set :session_secret, '9771aff2c634257053c62ba072c54754bd2cc92739b37e81c3eda505da48c2ec' end use OmniAuth::Builder do provider :auth0, client_id, secret, domain, options end get '/auth/auth0/callback' do MultiJson.encode(env['omniauth.auth']) end end end end OmniAuth.config.logger = Logger.new('/dev/null') omniauth-auth0-3.1.0/EXAMPLES.md0000644000004100000410000001375214350575705016171 0ustar www-datawww-data* [Example of the resulting authentication hash](#example-of-the-resulting-authentication-hash) * [Send additional authentication parameters](#send-additional-authentication-parameters) * [Query Parameter Options](#query-parameter-options) * [Auth0 Organizations](#auth0-organizations) - [Logging in with an Organization](#logging-in-with-an-organization) - [Validating Organizations when using Organization Login Prompt](#validating-organizations-when-using-organization-login-prompt) - [Accepting user invitations](#accepting-user-invitations) ### Example of the resulting authentication hash The Auth0 strategy will provide the standard OmniAuth hash attributes: - `:provider` - the name of the strategy, in this case `auth0` - `:uid` - the user identifier - `:info` - the result of the call to `/userinfo` using OmniAuth standard attributes - `:credentials` - tokens requested and data - `:extra` - Additional info obtained from calling `/userinfo` in the `:raw_info` property ```ruby { :provider => 'auth0', :uid => 'auth0|USER_ID', :info => { :name => 'John Foo', :email => 'johnfoo@example.org', :nickname => 'john', :image => 'https://example.org/john.jpg' }, :credentials => { :token => 'ACCESS_TOKEN', :expires_at => 1485373937, :expires => true, :refresh_token => 'REFRESH_TOKEN', :id_token => 'JWT_ID_TOKEN', :token_type => 'bearer', }, :extra => { :raw_info => { :email => 'johnfoo@example.org', :email_verified => 'true', :name => 'John Foo', :picture => 'https://example.org/john.jpg', :user_id => 'auth0|USER_ID', :nickname => 'john', :created_at => '2014-07-15T17:19:50.387Z' } } } ``` ## Send additional authentication parameters To send additional parameters during login, you can specify them when you register the provider: ```ruby provider :auth0, ENV['AUTH0_CLIENT_ID'], ENV['AUTH0_CLIENT_SECRET'], ENV['AUTH0_DOMAIN'], { authorize_params: { scope: 'openid read:users write:order', audience: 'https://mydomain/api', max_age: 3600 # time in seconds authentication is valid } } ``` This will tell the strategy to send those parameters on every authentication request. ## Query Parameter Options In some scenarios, you may need to pass specific query parameters to `/authorize`. The following parameters are available to enable this: - `connection` - `connection_scope` - `prompt` - `screen_hint` (only relevant to New Universal Login Experience) - `organization` - `invitation` Simply pass these query parameters to your OmniAuth redirect endpoint to enable their behavior. ## Auth0 Organizations [Organizations](https://auth0.com/docs/organizations) is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications. Note that Organizations is currently only available to customers on our Enterprise and Startup subscription plans. ### Logging in with an Organization Logging in with an Organization is as easy as passing the parameters to the authorize endpoint. You can do this with ```ruby <%= button_to 'Login', 'auth/auth0', method: :post, params: { # Found in your Auth0 dashboard, under Organization settings: organization: '{AUTH0_ORGANIZATION}' } %> ``` Alternatively you can configure the organization when you register the provider: ```ruby provider :auth0, ENV['AUTH0_CLIENT_ID'], ENV['AUTH0_CLIENT_SECRET'], ENV['AUTH0_DOMAIN'] { authorize_params: { scope: 'openid read:users', audience: 'https://{AUTH0_DOMAIN}/api', organization: '{AUTH0_ORGANIZATION}' } } ``` When passing `openid` to the scope and `organization` to the authorize params, you will receive an ID token on callback with the `org_id` claim. This claim is validated for you by the SDK. ### Validating Organizations when using Organization Login Prompt When Organization login prompt is enabled on your application, but you haven't specified an Organization for the application's authorization endpoint, the `org_id` claim will be present on the ID token, and should be validated to ensure that the value received is expected or known. Normally, validating the issuer would be enough to ensure that the token was issued by Auth0, and this check is performed by the SDK. However, in the case of organizations, additional checks should be made so that the organization within an Auth0 tenant is expected. In particular, the `org_id` claim should be checked to ensure it is a value that is already known to the application. This could be validated against a known list of organization IDs, or perhaps checked in conjunction with the current request URL. e.g. the sub-domain may hint at what organization should be used to validate the ID Token. Here is an example using it in your `callback` method ```ruby def callback claims = request.env['omniauth.auth']['extra']['raw_info'] if claims["org"] && claims["org"] !== expected_org redirect_to '/unauthorized', status: 401 else session[:userinfo] = claims redirect_to '/dashboard' end end ``` For more information, please read [Work with Tokens and Organizations](https://auth0.com/docs/organizations/using-tokens) on Auth0 Docs. ### Accepting user invitations Auth0 Organizations allow users to be invited using emailed links, which will direct a user back to your application. The URL the user will arrive at is based on your configured `Application Login URI`, which you can change from your Application's settings inside the Auth0 dashboard. When the user arrives at your application using an invite link, you can expect three query parameters to be provided: `invitation`, `organization`, and `organization_name`. These will always be delivered using a GET request. You can then supply those parametrs to a `button_to` or `link_to` helper ```ruby <%= button_to 'Login', 'auth/auth0', method: :post, params: { organization: '{YOUR_ORGANIZATION_ID}', invitation: '{INVITE_CODE}' } %> ``` omniauth-auth0-3.1.0/CHANGELOG.md0000644000004100000410000003131214350575705016232 0ustar www-datawww-data# Change Log ## [v3.1.0](https://github.com/auth0/omniauth-auth0/tree/v3.1.0) (2022-11-04) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v3.0.0...v3.1.0) **Added** - Add ui_locales to permitted params [\#135](https://github.com/auth0/omniauth-auth0/pull/135) ([martijn](https://github.com/martijn)) **Changed** - Store plain Hash in session['authorize_params'] [\#150](https://github.com/auth0/omniauth-auth0/pull/150) ([santry](https://github.com/santry)) - Redesign readme to match new style [\#148](https://github.com/auth0/omniauth-auth0/pull/148) ([stevehobbsdev](https://github.com/stevehobbsdev)) **Fixed** - Fix authentication hash link in code sample [\#153](https://github.com/auth0/omniauth-auth0/pull/153) ([ewanharris](https://github.com/ewanharris)) **Security** - [Snyk] Fix for 1 vulnerabilities [\#149](https://github.com/auth0/omniauth-auth0/pull/149) ([snyk-bot](https://github.com/snyk-bot)) - Bump addressable from 2.7.0 to 2.8.0 [\#133](https://github.com/auth0/omniauth-auth0/pull/133) ([dependabot[bot]](https://github.com/apps/dependabot)) - [Snyk] Security upgrade webmock from 3.12.2 to 3.12.2 [\#134](https://github.com/auth0/omniauth-auth0/pull/134) ([snyk-bot](https://github.com/snyk-bot)) ## [v3.0.0](https://github.com/auth0/omniauth-auth0/tree/v3.0.0) (2021-04-14) Version 3.0 introduces [Omniauth v2.0](https://github.com/omniauth/omniauth/releases/tag/v2.0.0) which addresses [CVE-2015-9284](https://nvd.nist.gov/vuln/detail/CVE-2015-9284). Omniauth now defaults to only allow `POST` as the allowed request_phase method. This was previously handled through the recommended [mitigation](https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284) using the `omniauth-rails_csrf_protection v0.x.x` gem to provide CSRF protection. ### Upgrading to omniauth-rails_csrf_protection v1.0.0 If you are using `omniauth-rails_csrf_protection` to provide CSRF protection, you will need to be upgrade to `1.x.x`. ### BREAKING CHANGES Now that OmniAuth now defaults to only `POST` as the allowed request_phase method, if you aren't already, you will need to convert any login links to use [form helpers](https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for) with the `POST` method. ```html+ruby # OLD -- GET request Login # NEW Example #1 -- POST request <%= link_to 'Login', 'auth/auth0', method: :post %> # NEW Example #2 -- POST request <%= button_to 'Login', 'auth/auth0', method: :post %> # NEW Example #3 -- POST request <%= form_tag('/auth/auth0', method: :post) do %> <% end %> ``` ### Allowing GET Requests In the scenario you absolutely must use GET requests as an allowed request method for authentication, you can override the protection provided with the following config override: ```ruby # Allowing GET requests will expose you to CVE-2015-9284 OmniAuth.config.allowed_request_methods = [:get, :post] ``` ## [v2.6.0](https://github.com/auth0/omniauth-auth0/tree/v2.6.0) (2021-04-01) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.5.0...v2.6.0) **Added** - Org Support [SDK-2395] [\#124](https://github.com/auth0/omniauth-auth0/pull/124) ([davidpatrick](https://github.com/davidpatrick)) - Add login_hint to permitted params [\#123](https://github.com/auth0/omniauth-auth0/pull/123) ([Roriz](https://github.com/Roriz)) ## [v2.5.0](https://github.com/auth0/omniauth-auth0/tree/v2.5.0) (2021-01-21) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.4.2...v2.5.0) **Added** - Parsing claims from the id_token [\#120](https://github.com/auth0/omniauth-auth0/pull/120) ([davidpatrick](https://github.com/davidpatrick)) **Changed** - Setup build matrix in CI [\#116](https://github.com/auth0/omniauth-auth0/pull/116) ([dmathieu](https://github.com/dmathieu)) **Fixed** - Fixes params passed to authorize [\#119](https://github.com/auth0/omniauth-auth0/pull/119) ([davidpatrick](https://github.com/davidpatrick)) ## [v2.4.2](https://github.com/auth0/omniauth-auth0/tree/v2.4.2) (2021-01-19) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.4.1...v2.4.2) **Fixed** - Lock Omniauth to 1.9 in gemspec ## [v2.4.1](https://github.com/auth0/omniauth-auth0/tree/v2.4.1) (2020-10-08) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.4.0...v2.4.1) **Fixed** - Verify the JWT Signature [\#109](https://github.com/auth0/omniauth-auth0/pull/109) ([jimmyjames](https://github.com/jimmyjames)) ## [v2.4.0](https://github.com/auth0/omniauth-auth0/tree/v2.4.0) (2020-09-22) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.3.1...v2.4.0) **Security** - Bump rack from 2.2.2 to 2.2.3 [\#107](https://github.com/auth0/omniauth-auth0/pull/107) ([dependabot](https://github.com/dependabot)) - Update dependencies [\#100](https://github.com/auth0/omniauth-auth0/pull/100) ([Albalmaceda](https://github.com/Albalmaceda)) **Added** - Add support for screen_hint=signup param [\#103](https://github.com/auth0/omniauth-auth0/pull/103) ([bbean86](https://github.com/bbean86)) - Add support for `connection_scope` in params [\#99](https://github.com/auth0/omniauth-auth0/pull/99) ([felixclack](https://github.com/felixclack)) ## [v2.3.1](https://github.com/auth0/omniauth-auth0/tree/v2.3.1) (2020-03-27) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.3.0...v2.3.1) **Fixed bugs:** - Fixes dependency issue [\#97](https://github.com/auth0/omniauth-auth0/pull/97) ([davidpatrick](https://github.com/davidpatrick)) - Fix "NameError: uninitialized constant OmniAuth::Auth0::TokenValidationError" [\#96](https://github.com/auth0/omniauth-auth0/pull/96) ([stefanwork](https://github.com/stefanwork)) ## [v2.3.0](https://github.com/auth0/omniauth-auth0/tree/v2.3.0) (2020-03-06) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.2.0...v2.3.0) **Added** - Improved OIDC Compliance [\#92](https://github.com/auth0/omniauth-auth0/pull/92) ([davidpatrick](https://github.com/davidpatrick)) ## [v2.2.0](https://github.com/auth0/omniauth-auth0/tree/v2.2.0) (2018-04-18) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.1.0...v2.2.0) **Closed issues** - It supports custom domain? [\#71](https://github.com/auth0/omniauth-auth0/issues/71) - Valid Login, No Details: email=nil image=nil name="github|38257089" nickname=nil [\#70](https://github.com/auth0/omniauth-auth0/issues/70) **Added** - Custom issuer [\#77](https://github.com/auth0/omniauth-auth0/pull/77) ([ryan-rosenfeld](https://github.com/ryan-rosenfeld)) - Add telemetry to token endpoint [\#74](https://github.com/auth0/omniauth-auth0/pull/74) ([joshcanhelp](https://github.com/joshcanhelp)) **Changed** - Remove telemetry from authorize URL [\#75](https://github.com/auth0/omniauth-auth0/pull/75) ([joshcanhelp](https://github.com/joshcanhelp)) ## [v2.1.0](https://github.com/auth0/omniauth-auth0/tree/v2.1.0) (2018-10-30) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v2.0.0...v2.1.0) **Closed issues** - URL should be spelled uppercase outside of code [\#64](https://github.com/auth0/omniauth-auth0/issues/64) - Add prompt=none authorization param handler [\#58](https://github.com/auth0/omniauth-auth0/issues/58) - Could not find a valid mapping for path "/auth/oauth2/callback" [\#56](https://github.com/auth0/omniauth-auth0/issues/56) - I had to downgrade my gems to use this strategy :-( [\#53](https://github.com/auth0/omniauth-auth0/issues/53) - CSRF detected [\#49](https://github.com/auth0/omniauth-auth0/issues/49) - /auth/:provider route not registered? [\#47](https://github.com/auth0/omniauth-auth0/issues/47) **Added** - Add ID token validation [\#62](https://github.com/auth0/omniauth-auth0/pull/62) ([joshcanhelp](https://github.com/joshcanhelp)) - Silent authentication [\#59](https://github.com/auth0/omniauth-auth0/pull/59) ([batalla3692](https://github.com/batalla3692)) - Pass connection parameter to auth0 [\#54](https://github.com/auth0/omniauth-auth0/pull/54) ([tomgi](https://github.com/tomgi)) **Changed** - Update to omniauth-oauth2 [\#55](https://github.com/auth0/omniauth-auth0/pull/55) ([chills42](https://github.com/chills42)) **Fixed** - Fix Rubocop errors [\#66](https://github.com/auth0/omniauth-auth0/pull/66) ([joshcanhelp](https://github.com/joshcanhelp)) - Fix minute bug in README.md [\#63](https://github.com/auth0/omniauth-auth0/pull/63) ([rahuldess](https://github.com/rahuldess)) ## [v2.0.0](https://github.com/auth0/omniauth-auth0/tree/v2.0.0) (2017-01-25) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v1.4.1...v2.0.0) Updated library to handle OIDC conformant clients and OAuth2 features in Auth0. This affects how the `credentials` and `info` attributes are populated since the payload of /oauth/token and /userinfo are different when using OAuth2/OIDC features. The `credentials` hash will always have an `access_token` and might have a `refresh_token` (if it's allowed in your API settings in Auth0 dashboard and requested using `offline_access` scope) and an `id_token` (scope `openid` is needed for Auth0 to return it). The `info` object will use the [OmniAuth schema](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later) after calling /userinfo: - name: `name` attribute in userinfo response or `sub` if not available. - email: `email` attribute in userinfo response. - nickname: `nickname` attribute in userinfo response. - image: `picture` attribute in userinfo response. Also in `extra` will have in `raw_info` the full /userinfo response. **Fixed** - Use image attribute of omniauth instead of picture [\#45](https://github.com/auth0/omniauth-auth0/pull/45) ([hzalaz](https://github.com/hzalaz)) - Rework strategy to handle OAuth and OIDC [\#44](https://github.com/auth0/omniauth-auth0/pull/44) ([hzalaz](https://github.com/hzalaz)) - lock v10 update, dependencies update [\#41](https://github.com/auth0/omniauth-auth0/pull/41) ([Amialc](https://github.com/Amialc)) ## [v1.4.2](https://github.com/auth0/omniauth-auth0/tree/v1.4.2) (2016-06-13) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v1.4.1...v1.4.2) **Added** - Link to OmniAuth site [\#36](https://github.com/auth0/omniauth-auth0/pull/36) ([jghaines](https://github.com/jghaines)) - add ssl fix to RoR example [\#31](https://github.com/auth0/omniauth-auth0/pull/31) ([Amialc](https://github.com/Amialc)) - Update LICENSE [\#17](https://github.com/auth0/omniauth-auth0/pull/17) ([aguerere](https://github.com/aguerere)) **Changed** - Update lock to version 9 [\#34](https://github.com/auth0/omniauth-auth0/pull/34) ([Annyv2](https://github.com/Annyv2)) - Update Gemfile [\#22](https://github.com/auth0/omniauth-auth0/pull/22) ([Annyv2](https://github.com/Annyv2)) - Update lock [\#15](https://github.com/auth0/omniauth-auth0/pull/15) ([Annyv2](https://github.com/Annyv2)) **Fixed** - Fix setup [\#38](https://github.com/auth0/omniauth-auth0/pull/38) ([deepak](https://github.com/deepak)) - Added missing instruction [\#30](https://github.com/auth0/omniauth-auth0/pull/30) ([Annyv2](https://github.com/Annyv2)) - Fixes undefined Auth0Lock issue [\#28](https://github.com/auth0/omniauth-auth0/pull/28) ([Annyv2](https://github.com/Annyv2)) - Update Readme [\#27](https://github.com/auth0/omniauth-auth0/pull/27) ([Annyv2](https://github.com/Annyv2)) ## [v1.4.1](https://github.com/auth0/omniauth-auth0/tree/v1.4.1) (2015-11-18) [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v1.4.0...v1.4.1) **Merged pull requests:** - Updating the strategy to set the refresh token in the credentials [\#14](https://github.com/auth0/omniauth-auth0/pull/14) ([LindseyB](https://github.com/LindseyB)) - Update README.md [\#13](https://github.com/auth0/omniauth-auth0/pull/13) ([Annyv2](https://github.com/Annyv2)) - Update home.js [\#12](https://github.com/auth0/omniauth-auth0/pull/12) ([Annyv2](https://github.com/Annyv2)) - Add nested module in version.rb [\#9](https://github.com/auth0/omniauth-auth0/pull/9) ([l4u](https://github.com/l4u)) ## [v1.4.0](https://github.com/auth0/omniauth-auth0/tree/v1.4.0) (2015-06-01) **Merged pull requests:** - Client headers [\#8](https://github.com/auth0/omniauth-auth0/pull/8) ([benschwarz](https://github.com/benschwarz)) - Web application seed with Lock [\#5](https://github.com/auth0/omniauth-auth0/pull/5) ([sandrinodimattia](https://github.com/sandrinodimattia)) - Create LICENSE.md [\#4](https://github.com/auth0/omniauth-auth0/pull/4) ([pose](https://github.com/pose)) - Update README.md [\#3](https://github.com/auth0/omniauth-auth0/pull/3) ([pose](https://github.com/pose)) - Fix Markdown typo [\#2](https://github.com/auth0/omniauth-auth0/pull/2) ([dentarg](https://github.com/dentarg)) \* _This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)_ omniauth-auth0-3.1.0/.rubocop.yml0000644000004100000410000000056014350575705016674 0ustar www-datawww-dataMetrics/BlockLength: Exclude: - 'Rakefile' - '**/*.rake' - 'spec/**/*.rb' - 'spec/spec_helper.rb' Metrics/MethodLength: Exclude: - 'Rakefile' - '**/*.rake' - 'spec/**/*.rb' Metrics/AbcSize: Exclude: - 'Rakefile' - '**/*.rake' - 'spec/**/*.rb' - 'spec/spec_helper.rb' AllCops: Exclude: - 'omniauth-auth0.gemspec' omniauth-auth0-3.1.0/.gitignore0000644000004100000410000000015014350575705016405 0ustar www-datawww-data.ruby-version coverage *.gem .#* .env log/ tmp/ ## Environment normalization: /.bundle /vendor/bundle omniauth-auth0-3.1.0/.snyk0000644000004100000410000000047114350575705015410 0ustar www-datawww-data# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. version: v1.13.5 # ignores vulnerabilities until expiry date; change duration by modifying expiry date ignore: SNYK-RUBY-OMNIAUTH-174820: - '*': reason: Not affected. expires: 2020-01-01T00:00:00.000Z patch: {} omniauth-auth0-3.1.0/LICENSE0000644000004100000410000000213514350575705015427 0ustar www-datawww-dataThe MIT License (MIT) Copyright (c) 2015 Auth0, Inc. (http://auth0.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. omniauth-auth0-3.1.0/examples/0000755000004100000410000000000014350575705016237 5ustar www-datawww-dataomniauth-auth0-3.1.0/examples/sinatra/0000755000004100000410000000000014350575705017700 5ustar www-datawww-dataomniauth-auth0-3.1.0/examples/sinatra/config.ru0000644000004100000410000000012214350575705021510 0ustar www-datawww-datarequire File.expand_path('app', File.dirname(__FILE__)) run Sinatra::Application omniauth-auth0-3.1.0/examples/sinatra/app.rb0000644000004100000410000000043414350575705021006 0ustar www-datawww-datarequire 'sinatra' require 'omniauth-auth0' require 'dotenv/load' use OmniAuth::Builder do provider :auth0, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'], ENV['DOMAIN'] end enable :sessions set :session_secret, ENV['SESSION_SECRET'] get '/' do 'Auth0 OmniAuth Example for Sinatra' end omniauth-auth0-3.1.0/.gemrelease0000644000004100000410000000002114350575705016524 0ustar www-datawww-databump: tag: trueomniauth-auth0-3.1.0/Rakefile0000755000004100000410000000103714350575705016072 0ustar www-datawww-data#!/usr/bin/env rake require 'bundler/gem_tasks' require 'rspec/core/rake_task' desc 'Run specs' RSpec::Core::RakeTask.new begin require 'rubocop/rake_task' RuboCop::RakeTask.new rescue LoadError task :rubocop do warn 'Rubocop is disabled' end end namespace :sinatra do task :start do system 'bundle exec shotgun' \ ' --server=thin --port=3000' \ ' examples/sinatra/config.ru' end end desc 'Run specs' task default: %i[spec rubocop] task test: :spec task :guard do system 'bundle exec guard' end omniauth-auth0-3.1.0/lib/0000755000004100000410000000000014350575705015167 5ustar www-datawww-dataomniauth-auth0-3.1.0/lib/omniauth/0000755000004100000410000000000014350575705017013 5ustar www-datawww-dataomniauth-auth0-3.1.0/lib/omniauth/strategies/0000755000004100000410000000000014350575705021165 5ustar www-datawww-dataomniauth-auth0-3.1.0/lib/omniauth/strategies/auth0.rb0000644000004100000410000001156714350575705022545 0ustar www-datawww-data# frozen_string_literal: true require 'base64' require 'uri' require 'securerandom' require 'omniauth-oauth2' require 'omniauth/auth0/jwt_validator' require 'omniauth/auth0/telemetry' require 'omniauth/auth0/errors' module OmniAuth module Strategies # Auth0 OmniAuth strategy class Auth0 < OmniAuth::Strategies::OAuth2 include OmniAuth::Auth0::Telemetry option :name, 'auth0' args %i[ client_id client_secret domain ] # Setup client URLs used during authentication def client options.client_options.site = domain_url options.client_options.authorize_url = '/authorize' options.client_options.token_url = '/oauth/token' options.client_options.userinfo_url = '/userinfo' super end # Use the "sub" key of the userinfo returned # as the uid (globally unique string identifier). uid { raw_info['sub'] } # Build the API credentials hash with returned auth data. credentials do credentials = { 'token' => access_token.token, 'expires' => true } if access_token.params credentials.merge!( 'id_token' => access_token.params['id_token'], 'token_type' => access_token.params['token_type'], 'refresh_token' => access_token.refresh_token ) end # Retrieve and remove authorization params from the session session_authorize_params = session['authorize_params'] || {} session.delete('authorize_params') auth_scope = session_authorize_params[:scope] if auth_scope.respond_to?(:include?) && auth_scope.include?('openid') # Make sure the ID token can be verified and decoded. jwt_validator.verify(credentials['id_token'], session_authorize_params) end credentials end # Store all raw information for use in the session. extra do { raw_info: raw_info } end # Build a hash of information about the user # with keys taken from the Auth Hash Schema. info do { name: raw_info['name'] || raw_info['sub'], nickname: raw_info['nickname'], email: raw_info['email'], image: raw_info['picture'] } end # Define the parameters used for the /authorize endpoint def authorize_params params = super %w[connection connection_scope prompt screen_hint login_hint organization invitation ui_locales].each do |key| params[key] = request.params[key] if request.params.key?(key) end # Generate nonce params[:nonce] = SecureRandom.hex # Generate leeway if none exists params[:leeway] = 60 unless params[:leeway] # Store authorize params in the session for token verification session['authorize_params'] = params.to_hash params end def build_access_token options.token_params[:headers] = { 'Auth0-Client' => telemetry_encoded } super end # Declarative override for the request phase of authentication def request_phase if no_client_id? # Do we have a client_id for this Application? fail!(:missing_client_id) elsif no_client_secret? # Do we have a client_secret for this Application? fail!(:missing_client_secret) elsif no_domain? # Do we have a domain for this Application? fail!(:missing_domain) else # All checks pass, run the Oauth2 request_phase method. super end end def callback_phase super rescue OmniAuth::Auth0::TokenValidationError => e fail!(:token_validation_error, e) end private def jwt_validator @jwt_validator ||= OmniAuth::Auth0::JWTValidator.new(options) end # Parse the raw user info. def raw_info return @raw_info if @raw_info if access_token["id_token"] claims, header = jwt_validator.decode(access_token["id_token"]) @raw_info = claims else userinfo_url = options.client_options.userinfo_url @raw_info = access_token.get(userinfo_url).parsed end return @raw_info end # Check if the options include a client_id def no_client_id? ['', nil].include?(options.client_id) end # Check if the options include a client_secret def no_client_secret? ['', nil].include?(options.client_secret) end # Check if the options include a domain def no_domain? ['', nil].include?(options.domain) end # Normalize a domain to a URL. def domain_url domain_url = URI(options.domain) domain_url = URI("https://#{domain_url}") if domain_url.scheme.nil? domain_url.to_s end end end end omniauth-auth0-3.1.0/lib/omniauth/auth0/0000755000004100000410000000000014350575705020034 5ustar www-datawww-dataomniauth-auth0-3.1.0/lib/omniauth/auth0/jwt_validator.rb0000644000004100000410000002515014350575705023235 0ustar www-datawww-datarequire 'base64' require 'uri' require 'json' require 'omniauth' require 'omniauth/auth0/errors' module OmniAuth module Auth0 # JWT Validator class class JWTValidator attr_accessor :issuer, :domain # Initializer # @param options object # options.domain - Application domain. # options.issuer - Application issuer (optional). # options.client_id - Application Client ID. # options.client_secret - Application Client Secret. def initialize(options, authorize_params = {}) @domain = uri_string(options.domain) # Use custom issuer if provided, otherwise use domain @issuer = @domain @issuer = uri_string(options.issuer) if options.respond_to?(:issuer) @client_id = options.client_id @client_secret = options.client_secret end # Verify a token's signature. Only tokens signed with the RS256 or HS256 signatures are supported. # Deprecated: Please use `decode` instead # @return array - The token's key and signing algorithm def verify_signature(jwt) head = token_head(jwt) key, alg = extract_key(head) # Call decode to verify the signature JWT.decode(jwt, key, true, decode_opts(alg)) return key, alg end # Decodes a JWT and verifies it's signature. Only tokens signed with the RS256 or HS256 signatures are supported. # @param jwt string - JWT to verify. # @return hash - The decoded token, if there were no exceptions. # @see https://github.com/jwt/ruby-jwt def decode(jwt) head = token_head(jwt) key, alg = extract_key(head) # Call decode to verify the signature JWT.decode(jwt, key, true, decode_opts(alg)) end # Verify a JWT. # @param jwt string - JWT to verify. # @param authorize_params hash - Authorization params to verify on the JWT # @return hash - The verified token payload, if there were no exceptions. def verify(jwt, authorize_params = {}) if !jwt raise OmniAuth::Auth0::TokenValidationError.new('ID token is required but missing') end parts = jwt.split('.') if parts.length != 3 raise OmniAuth::Auth0::TokenValidationError.new('ID token could not be decoded') end id_token, header = decode(jwt) verify_claims(id_token, authorize_params) return id_token end # Get the decoded head segment from a JWT. # @return hash - The parsed head of the JWT passed, empty hash if not. def token_head(jwt) jwt_parts = jwt.split('.') return {} if blank?(jwt_parts) || blank?(jwt_parts[0]) json_parse(Base64.decode64(jwt_parts[0])) end # Get the JWKS from the issuer and return a public key. # @param x5c string - X.509 certificate chain from a JWKS. # @return key - The X.509 certificate public key. def jwks_public_cert(x5c) x5c = Base64.decode64(x5c) # https://docs.ruby-lang.org/en/2.4.0/OpenSSL/X509/Certificate.html OpenSSL::X509::Certificate.new(x5c).public_key end # Return a specific key from a JWKS object. # @param key string - Key to find in the JWKS. # @param kid string - Key ID to identify the right JWK. # @return nil|string def jwks_key(key, kid) return nil if blank?(jwks[:keys]) matching_jwk = jwks[:keys].find { |jwk| jwk[:kid] == kid } matching_jwk[key] if matching_jwk end private # Get the JWT decode options. We disable the claim checks since we perform our claim validation logic # Docs: https://github.com/jwt/ruby-jwt # @return hash def decode_opts(alg) { algorithm: alg, verify_expiration: false, verify_iat: false, verify_iss: false, verify_aud: false, verify_jti: false, verify_subj: false, verify_not_before: false } end def extract_key(head) if head[:alg] == 'RS256' key, alg = [rs256_decode_key(head[:kid]), head[:alg]] elsif head[:alg] == 'HS256' key, alg = [@client_secret, head[:alg]] else raise OmniAuth::Auth0::TokenValidationError.new("Signature algorithm of #{head[:alg]} is not supported. Expected the ID token to be signed with RS256 or HS256") end end def rs256_decode_key(kid) jwks_x5c = jwks_key(:x5c, kid) if jwks_x5c.nil? raise OmniAuth::Auth0::TokenValidationError.new("Could not find a public key for Key ID (kid) '#{kid}'") end jwks_public_cert(jwks_x5c.first) end # Get a JWKS from the domain # @return void def jwks jwks_uri = URI(@domain + '.well-known/jwks.json') @jwks ||= json_parse(Net::HTTP.get(jwks_uri)) end # Rails Active Support blank method. # @param obj object - Object to check for blankness. # @return boolean def blank?(obj) obj.respond_to?(:empty?) ? obj.empty? : !obj end # Parse JSON with symbolized names. # @param json string - JSON to parse. # @return hash def json_parse(json) JSON.parse(json, symbolize_names: true) end # Parse a URI into the desired string format # @param uri - the URI to parse # @return string def uri_string(uri) temp_domain = URI(uri) temp_domain = URI("https://#{uri}") unless temp_domain.scheme temp_domain = temp_domain.to_s temp_domain.end_with?('/') ? temp_domain : "#{temp_domain}/" end def verify_claims(id_token, authorize_params) leeway = authorize_params[:leeway] || 60 max_age = authorize_params[:max_age] nonce = authorize_params[:nonce] organization = authorize_params[:organization] verify_iss(id_token) verify_sub(id_token) verify_aud(id_token) verify_expiration(id_token, leeway) verify_iat(id_token) verify_nonce(id_token, nonce) verify_azp(id_token) verify_auth_time(id_token, leeway, max_age) verify_org(id_token, organization) end def verify_iss(id_token) issuer = id_token['iss'] if !issuer raise OmniAuth::Auth0::TokenValidationError.new("Issuer (iss) claim must be a string present in the ID token") elsif @issuer != issuer raise OmniAuth::Auth0::TokenValidationError.new("Issuer (iss) claim mismatch in the ID token, expected (#{@issuer}), found (#{id_token['iss']})") end end def verify_sub(id_token) subject = id_token['sub'] if !subject || !subject.is_a?(String) || subject.empty? raise OmniAuth::Auth0::TokenValidationError.new('Subject (sub) claim must be a string present in the ID token') end end def verify_aud(id_token) audience = id_token['aud'] if !audience || !(audience.is_a?(String) || audience.is_a?(Array)) raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim must be a string or array of strings present in the ID token") elsif audience.is_a?(Array) && !audience.include?(@client_id) raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim mismatch in the ID token; expected #{@client_id} but was not one of #{audience.join(', ')}") elsif audience.is_a?(String) && audience != @client_id raise OmniAuth::Auth0::TokenValidationError.new("Audience (aud) claim mismatch in the ID token; expected #{@client_id} but found #{audience}") end end def verify_expiration(id_token, leeway) expiration = id_token['exp'] if !expiration || !expiration.is_a?(Integer) raise OmniAuth::Auth0::TokenValidationError.new("Expiration time (exp) claim must be a number present in the ID token") elsif expiration <= Time.now.to_i - leeway raise OmniAuth::Auth0::TokenValidationError.new("Expiration time (exp) claim error in the ID token; current time (#{Time.now}) is after expiration time (#{Time.at(expiration + leeway)})") end end def verify_iat(id_token) if !id_token['iat'] raise OmniAuth::Auth0::TokenValidationError.new("Issued At (iat) claim must be a number present in the ID token") end end def verify_nonce(id_token, nonce) if nonce received_nonce = id_token['nonce'] if !received_nonce raise OmniAuth::Auth0::TokenValidationError.new("Nonce (nonce) claim must be a string present in the ID token") elsif nonce != received_nonce raise OmniAuth::Auth0::TokenValidationError.new("Nonce (nonce) claim value mismatch in the ID token; expected (#{nonce}), found (#{received_nonce})") end end end def verify_azp(id_token) audience = id_token['aud'] if audience.is_a?(Array) && audience.length > 1 azp = id_token['azp'] if !azp || !azp.is_a?(String) raise OmniAuth::Auth0::TokenValidationError.new("Authorized Party (azp) claim must be a string present in the ID token when Audience (aud) claim has multiple values") elsif azp != @client_id raise OmniAuth::Auth0::TokenValidationError.new("Authorized Party (azp) claim mismatch in the ID token; expected (#{@client_id}), found (#{azp})") end end end def verify_auth_time(id_token, leeway, max_age) if max_age auth_time = id_token['auth_time'] if !auth_time || !auth_time.is_a?(Integer) raise OmniAuth::Auth0::TokenValidationError.new("Authentication Time (auth_time) claim must be a number present in the ID token when Max Age (max_age) is specified") elsif Time.now.to_i > auth_time + max_age + leeway; raise OmniAuth::Auth0::TokenValidationError.new("Authentication Time (auth_time) claim in the ID token indicates that too much time has passed since the last end-user authentication. Current time (#{Time.now}) is after last auth time (#{Time.at(auth_time + max_age + leeway)})") end end end def verify_org(id_token, organization) if organization org_id = id_token['org_id'] if !org_id || !org_id.is_a?(String) raise OmniAuth::Auth0::TokenValidationError.new("Organization Id (org_id) claim must be a string present in the ID token") elsif org_id != organization raise OmniAuth::Auth0::TokenValidationError.new("Organization Id (org_id) claim value mismatch in the ID token; expected '#{organization}', found '#{org_id}'") end end end end end end omniauth-auth0-3.1.0/lib/omniauth/auth0/errors.rb0000644000004100000410000000032214350575705021672 0ustar www-datawww-datamodule OmniAuth module Auth0 class TokenValidationError < StandardError attr_reader :error_reason def initialize(msg) @error_reason = msg super(msg) end end end endomniauth-auth0-3.1.0/lib/omniauth/auth0/telemetry.rb0000644000004100000410000000156114350575705022376 0ustar www-datawww-datarequire 'json' module OmniAuth module Auth0 # Module to provide necessary telemetry for API requests. module Telemetry # Return a telemetry hash to be encoded and sent to Auth0. # @return hash def telemetry telemetry = { name: 'omniauth-auth0', version: OmniAuth::Auth0::VERSION, env: { ruby: RUBY_VERSION } } add_rails_version telemetry end # JSON-ify and base64 encode the current telemetry. # @return string def telemetry_encoded Base64.urlsafe_encode64(JSON.dump(telemetry)) end private def add_rails_version(telemetry) return telemetry unless Gem.loaded_specs['rails'].respond_to? :version telemetry[:env][:rails] = Gem.loaded_specs['rails'].version.to_s telemetry end end end end omniauth-auth0-3.1.0/lib/omniauth-auth0/0000755000004100000410000000000014350575705020032 5ustar www-datawww-dataomniauth-auth0-3.1.0/lib/omniauth-auth0/version.rb0000644000004100000410000000010614350575705022041 0ustar www-datawww-datamodule OmniAuth module Auth0 VERSION = '3.1.0'.freeze end end omniauth-auth0-3.1.0/lib/omniauth-auth0.rb0000644000004100000410000000010514350575705020353 0ustar www-datawww-datarequire 'omniauth-auth0/version' require 'omniauth/strategies/auth0' omniauth-auth0-3.1.0/CONTRIBUTING.md0000644000004100000410000000430014350575705016647 0ustar www-datawww-data# Contribution **Thank you in advance for your contribution!** Please read [Auth0's contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) before beginning work on your contribution here. ## Environment setup The best way we've found to develop gems locally is by using a local setting for your Bundler config. First, checkout the project locally: ```bash $ pwd /PROJECT_ROOT/ $ mkdir vendor # if one does not exist $ echo "/vendor/" >> .gitignore $ git clone git@github.com:auth0/omniauth-auth0.git vendor/omniauth-auth0 Cloning into 'vendor/omniauth-auth0'... ``` Now, run the following command in your project root directory: ```bash $ bundle config --local local.omniauth-auth0 /PROJECT_ROOT/vendor/omniauth-auth0 You are replacing the current local value of local.omniauth-auth0, which is currently nil $ bundle config Settings are listed in order of priority. The top value will be used. local.omniauth-auth0 Set for your local app (/PROJECT_ROOT/.bundle/config): "/PROJECT_ROOT/vendor/omniauth-auth0" ``` Finally, add or change the gem include to add a `github:` param: ```ruby source 'https://rubygems.org' # ... # OmniAuth strategy for authenticating with Auth0 gem 'omniauth-auth0', github: 'auth0/omniauth-auth0' #.. ``` Now you should be able to make changes locally and have them reflected in your test app. Keep in mind you'll need to restart your app between changes. [Great explanation for why this setup works well](https://rossta.net/blog/how-to-specify-local-ruby-gems-in-your-gemfile.html). ## Testing Tests should be added for additional or modified functionality and all tests should run successfully before submitting a PR. ### Adding tests All new tests should be added to the `/spec/omniauth` directory. Testing resources, like JSON fixtures, should be added to the `/spec/resources` directory. ### Running tests Running tests is as simple as: ```bash $ bundle exec rake spec ``` ## Documentation Documentation for this gem is primarily done at the code level. All new methods should include a docblock at least. ## Code quality tools Code quality is enforced across the entire gem with Rubocop: ```bash $ bundle exec rake rubocop ``` omniauth-auth0-3.1.0/Guardfile0000644000004100000410000000027014350575705016245 0ustar www-datawww-dataguard :rspec, cmd: 'bundle exec rspec' do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } watch('spec/spec_helper.rb') { 'spec' } end omniauth-auth0-3.1.0/Gemfile0000644000004100000410000000077114350575705015721 0ustar www-datawww-datasource 'https://rubygems.org' gemspec gem 'gem-release', '~> 2' gem 'jwt', '~> 2' gem 'rake', '~> 13' group :development do gem 'dotenv', '~> 2' gem 'pry', '~> 0' gem 'rubocop', '~> 1', require: false gem 'shotgun', '~> 0' gem 'sinatra', '~> 2' gem 'thin', '~> 1' end group :test do gem 'guard-rspec', '~> 4', require: false gem 'listen', '~> 3' gem 'rack-test', '~> 2' gem 'rspec', '~> 3' gem 'simplecov-cobertura', '~> 2' gem 'webmock', '~> 3' gem 'multi_json', '~> 1' end omniauth-auth0-3.1.0/.semgrepignore0000644000004100000410000000004714350575705017271 0ustar www-datawww-dataexamples/ spec/ CHANGELOG.md README.md omniauth-auth0-3.1.0/.github/0000755000004100000410000000000014350575705015761 5ustar www-datawww-dataomniauth-auth0-3.1.0/.github/PULL_REQUEST_TEMPLATE.md0000644000004100000410000000274014350575705021565 0ustar www-datawww-data### Changes Please describe both what is changing and why this is important. Include: - Endpoints added, deleted, deprecated, or changed - Classes and methods added, deleted, deprecated, or changed - Screenshots of new or changed UI, if applicable - A summary of usage if this is a new feature or change to a public API (this should also be added to relevant documentation once released) ### References Please include relevant links supporting this change such as a: - support ticket - community post - StackOverflow post - support forum thread - related GitHub issue in this or another repo ### Testing Please describe how this can be tested by reviewers. Be specific about anything not tested and reasons why. If this library has unit and/or integration testing, tests should be added for new functionality and existing tests should complete without errors. * [ ] This change adds unit test coverage * [ ] This change has been tested on the latest version of the platform/language or why not ### Checklist * [ ] I have read the [Auth0 contribution guidelines](https://github.com/auth0/open-source-template/blob/master/GENERAL-CONTRIBUTING.md) * [ ] I have read the [Auth0 Code of Conduct](https://github.com/auth0/open-source-template/blob/master/CODE-OF-CONDUCT.md) * [ ] All existing and new tests complete without errors * [ ] All code quality tools/guidelines in the [CONTRIBUTING documentation](https://github.com/auth0/omniauth-auth0/blob/master/CONTRIBUTING.md) have been run/followed omniauth-auth0-3.1.0/.github/CODEOWNERS0000644000004100000410000000003214350575705017347 0ustar www-datawww-data* @auth0/dx-sdks-engineer omniauth-auth0-3.1.0/.github/stale.yml0000644000004100000410000000172414350575705017620 0ustar www-datawww-data# Configuration for probot-stale - https://github.com/probot/stale # Number of days of inactivity before an Issue or Pull Request becomes stale daysUntilStale: 90 # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. daysUntilClose: 7 # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable exemptLabels: [] # Set to true to ignore issues with an assignee (defaults to false) exemptAssignees: true # Label to use when marking as stale staleLabel: closed:stale # Comment to post when marking as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you have not received a response for our team (apologies for the delay) and this is still a blocker, please reply with additional information or just a ping. Thank you for your contribution! 🙇‍♂️omniauth-auth0-3.1.0/.github/workflows/0000755000004100000410000000000014350575705020016 5ustar www-datawww-dataomniauth-auth0-3.1.0/.github/workflows/semgrep.yml0000644000004100000410000000064314350575705022206 0ustar www-datawww-dataname: Semgrep on: pull_request: {} push: branches: ["master", "main"] schedule: - cron: '30 0 1,15 * *' jobs: semgrep: name: Scan runs-on: ubuntu-latest container: image: returntocorp/semgrep if: (github.actor != 'dependabot[bot]') steps: - uses: actions/checkout@v3 - run: semgrep ci env: SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} omniauth-auth0-3.1.0/.github/ISSUE_TEMPLATE/0000755000004100000410000000000014350575705020144 5ustar www-datawww-dataomniauth-auth0-3.1.0/.github/ISSUE_TEMPLATE/config.yml0000644000004100000410000000047214350575705022137 0ustar www-datawww-datablank_issues_enabled: false contact_links: - name: Auth0 Community url: https://community.auth0.com/c/sdks/5 about: Discuss this SDK in the Auth0 Community forums - name: Library Documentation url: https://github.com/auth0/omniauth-auth0#documentation about: Read the library docs on Auth0.com omniauth-auth0-3.1.0/.github/ISSUE_TEMPLATE/feature_request.md0000644000004100000410000000264014350575705023673 0ustar www-datawww-data--- name: Feature request about: Suggest an idea or a feature for this project title: '' labels: feature request assignees: '' --- ### Describe the problem you'd like to have solved ### Describe the ideal solution ## Alternatives and current work-arounds ### Additional information, if any omniauth-auth0-3.1.0/.github/ISSUE_TEMPLATE/report_a_bug.md0000644000004100000410000000375314350575705023146 0ustar www-datawww-data--- name: Report a bug about: Have you found a bug or issue? Create a bug report for this SDK title: '' labels: bug report assignees: '' --- ### Describe the problem ### What was the expected behavior? ### Reproduction - Step 1.. - Step 2.. - ... ### Environment - **Version of this library used:** - **Which framework are you using, if applicable:** - **Other modules/plugins/libraries that might be involved:** - **Any other relevant information you think would be useful:**omniauth-auth0-3.1.0/omniauth-auth0.gemspec0000644000004100000410000000231214350575705020627 0ustar www-datawww-data# -*- encoding: utf-8 -*- $LOAD_PATH.push File.expand_path('../lib', __FILE__) require 'omniauth-auth0/version' Gem::Specification.new do |s| s.name = 'omniauth-auth0' s.version = OmniAuth::Auth0::VERSION s.authors = ['Auth0'] s.email = ['info@auth0.com'] s.homepage = 'https://github.com/auth0/omniauth-auth0' s.summary = 'OmniAuth OAuth2 strategy for the Auth0 platform.' s.description = %q{Auth0 is an authentication broker that supports social identity providers as well as enterprise identity providers such as Active Directory, LDAP, Google Apps, Salesforce. OmniAuth is a library that standardizes multi-provider authentication for web applications. It was created to be powerful, flexible, and do as little as possible. omniauth-auth0 is the OmniAuth strategy for Auth0. } s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) } s.require_paths = ['lib'] s.add_runtime_dependency 'omniauth', '~> 2' s.add_runtime_dependency 'omniauth-oauth2', '~> 1' s.add_development_dependency 'bundler' s.license = 'MIT' end omniauth-auth0-3.1.0/opslevel.yml0000644000004100000410000000007414350575705016776 0ustar www-datawww-data--- version: 1 repository: owner: dx_sdks tier: tags: omniauth-auth0-3.1.0/.shiprc0000644000004100000410000000022314350575705015707 0ustar www-datawww-data{ "files": { "lib/omniauth-auth0/version.rb": [] }, "prebump": "bundle install && bundle exec rake test", "postbump": "bundle update" }omniauth-auth0-3.1.0/codecov.yml0000644000004100000410000000062614350575705016572 0ustar www-datawww-datacoverage: precision: 2 round: down range: "60...100" status: project: default: enabled: true target: auto threshold: 5% if_no_uploads: error patch: default: enabled: true target: 80% threshold: 30% if_no_uploads: error changes: default: enabled: true if_no_uploads: error comment: false