New upstream version 2.0.0
Pirate Praveen
6 years ago
0 | Metrics/BlockLength: | |
1 | Exclude: | |
2 | - 'Rakefile' | |
3 | - '**/*.rake' | |
4 | - 'spec/**/*.rb' | |
5 | - 'spec/spec_helper.rb' | |
6 | Metrics/MethodLength: | |
7 | Exclude: | |
8 | - 'Rakefile' | |
9 | - '**/*.rake' | |
10 | - 'spec/**/*.rb' | |
11 | Metrics/AbcSize: | |
12 | Exclude: | |
13 | - 'Rakefile' | |
14 | - '**/*.rake' | |
15 | - 'spec/**/*.rb' | |
16 | - 'spec/spec_helper.rb' | |
17 | AllCops: | |
18 | Exclude: | |
19 | - 'omniauth-auth0.gemspec' |
0 | 0 | # Change Log |
1 | 1 | |
2 | ## [v1.4.0](https://github.com/auth0/omniauth-auth0/tree/v1.4.0) (2015-06-01) | |
2 | ## [v2.0.0](https://github.com/auth0/omniauth-auth0/tree/v2.0.0) (2017-01-25) | |
3 | [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v1.4.1...v2.0.0) | |
4 | ||
5 | Updated library to handle OIDC conformant clients and OAuth2 features in Auth0. | |
6 | This affects how the `credentials` and `info` attributes are populated since the payload of /oauth/token and /userinfo are differnt when using OAuth2/OIDC features. | |
7 | ||
8 | 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). | |
9 | ||
10 | The `info` object will use the [OmniAuth schema](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema#schema-10-and-later) after calling /userinfo: | |
11 | ||
12 | - name: `name` attribute in userinfo response or `sub` if not available. | |
13 | - email: `email` attribute in userinfo response. | |
14 | - nickname: `nickname` attribute in userinfo response. | |
15 | - image: `picture` attribute in userinfo response. | |
16 | ||
17 | Also in `extra` will have in `raw_info` the full /userinfo response. | |
18 | ||
19 | ## [v1.4.1](https://github.com/auth0/omniauth-auth0/tree/v1.4.1) (2015-11-18) | |
20 | [Full Changelog](https://github.com/auth0/omniauth-auth0/compare/v1.4.0...v1.4.1) | |
3 | 21 | |
4 | 22 | **Merged pull requests:** |
5 | 23 | |
24 | - 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)) | |
25 | - Update README.md [\#13](https://github.com/auth0/omniauth-auth0/pull/13) ([Annyv2](https://github.com/Annyv2)) | |
26 | - Update home.js [\#12](https://github.com/auth0/omniauth-auth0/pull/12) ([Annyv2](https://github.com/Annyv2)) | |
27 | - Add nested module in version.rb [\#9](https://github.com/auth0/omniauth-auth0/pull/9) ([l4u](https://github.com/l4u)) | |
28 | ||
29 | ## [v1.4.0](https://github.com/auth0/omniauth-auth0/tree/v1.4.0) (2015-06-01) | |
30 | **Merged pull requests:** | |
31 | ||
6 | 32 | - Client headers [\#8](https://github.com/auth0/omniauth-auth0/pull/8) ([benschwarz](https://github.com/benschwarz)) |
7 | ||
8 | 33 | - Web application seed with Lock [\#5](https://github.com/auth0/omniauth-auth0/pull/5) ([sandrinodimattia](https://github.com/sandrinodimattia)) |
9 | ||
10 | 34 | - Create LICENSE.md [\#4](https://github.com/auth0/omniauth-auth0/pull/4) ([pose](https://github.com/pose)) |
11 | ||
12 | 35 | - Update README.md [\#3](https://github.com/auth0/omniauth-auth0/pull/3) ([pose](https://github.com/pose)) |
13 | ||
14 | 36 | - Fix Markdown typo [\#2](https://github.com/auth0/omniauth-auth0/pull/2) ([dentarg](https://github.com/dentarg)) |
15 | 37 | |
16 | 38 | |
17 | 39 | |
18 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*⏎ | |
40 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* |
0 | source "http://rubygems.org" | |
0 | source 'http://rubygems.org' | |
1 | 1 | |
2 | # Specify your gem's dependencies in omniauth-auth0.gemspec | |
3 | gemspec⏎ | |
2 | gemspec | |
3 | ||
4 | gem 'gem-release' | |
5 | gem 'rake' | |
6 | ||
7 | group :development do | |
8 | gem 'dotenv' | |
9 | gem 'pry' | |
10 | gem 'shotgun' | |
11 | gem 'sinatra' | |
12 | gem 'thin' | |
13 | end | |
14 | ||
15 | group :test do | |
16 | gem 'guard-rspec', require: false | |
17 | gem 'listen', '~> 3.1.5' | |
18 | gem 'rack-test' | |
19 | gem 'rspec', '~> 3.5' | |
20 | gem 'rubocop', '>= 0.30', platforms: [ | |
21 | :ruby_19, :ruby_20, :ruby_21, :ruby_22 | |
22 | ] | |
23 | gem 'simplecov' | |
24 | gem 'webmock' | |
25 | end |
0 | guard :rspec, cmd: 'bundle exec rspec' do | |
1 | watch(%r{^spec/.+_spec\.rb$}) | |
2 | watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } | |
3 | watch('spec/spec_helper.rb') { 'spec' } | |
4 | end |
0 | 0 | The MIT License (MIT) |
1 | 1 | |
2 | Copyright (c) 2014 Auth0 Inc. | |
2 | Copyright (c) 2015 Auth0, Inc. <support@auth0.com> (http://auth0.com) | |
3 | 3 | |
4 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | 5 | of this software and associated documentation files (the "Software"), to deal |
1 | 1 | |
2 | 2 | # OmniAuth Auth0 |
3 | 3 | |
4 | This is the official OmniAuth strategy for authenticating to [Auth0](https://auth0.com). | |
4 | This is the official [OmniAuth](https://github.com/intridea/omniauth) strategy for authenticating to [Auth0](https://auth0.com). | |
5 | 5 | |
6 | 6 | ## Installing |
7 | 7 | |
13 | 13 | |
14 | 14 | Then `bundle install`. |
15 | 15 | |
16 | ## Basic Usage | |
16 | ## Usage | |
17 | 17 | |
18 | 18 | ### Rails |
19 | 19 | |
23 | 23 | end |
24 | 24 | ``` |
25 | 25 | |
26 | If you want to force an identity provider you can simply redirect to the Omniauth path like this: | |
26 | Then to redirect to your tenant's hosted login page: | |
27 | 27 | |
28 | 28 | ```ruby |
29 | redirect_to '/auth/auth0?connection=CONNECTION_NAME' | |
29 | redirect_to '/auth/auth0' | |
30 | 30 | ``` |
31 | 31 | |
32 | 32 | ### Sinatra |
37 | 37 | end |
38 | 38 | ``` |
39 | 39 | |
40 | > Optional you can set the `:provider_ignores_state` passing a fourth parameter. By default it is true. | |
41 | ||
42 | If you want to force to force an identity provider you can simply redirect to Omniauth path like this: | |
40 | Then to redirect to your tenant's hosted login page: | |
43 | 41 | |
44 | 42 | ```ruby |
45 | redirect to('/auth/auth0?connection=CONNECTION_NAME') | |
43 | redirect to('/auth/auth0') | |
46 | 44 | ``` |
47 | 45 | |
48 | ### Login widget | |
46 | > You can customize your hosted login page in your [Auth0 Dashboard](https://manage.auth0.com/#/login_page) | |
49 | 47 | |
50 | Integrate the widget in one of your pages as described [here](http://auth0.com/docs/lock) or use links as described in the same link. | |
48 | ### Auth parameters | |
49 | ||
50 | To send additional parameters during login you can specify them when you register the provider | |
51 | ||
52 | ```ruby | |
53 | provider | |
54 | :auth0, | |
55 | ENV['AUTH0_CLIENT_ID'], | |
56 | ENV['AUTH0_CLIENT_SECRET'], | |
57 | ENV['AUTH0_DOMAIN'], | |
58 | { | |
59 | authorize_params: { | |
60 | scope: 'openid read:users write:order', | |
61 | audience: 'https://mydomain/api' | |
62 | } | |
63 | } | |
64 | ``` | |
65 | ||
66 | that will tell it to send those parameters on every Auth request. | |
67 | ||
68 | Or you can do it for a specific Auth request by adding them in the query parameter of the redirect url: | |
69 | ||
70 | ```ruby | |
71 | redirect_to '/auth/auth0?connection=google-oauth2' | |
72 | ``` | |
51 | 73 | |
52 | 74 | ### Auth Hash |
75 | ||
76 | Auth0 strategy will have the standard OmniAuth hash attributes: | |
77 | ||
78 | - provider: the name of the strategy, in this case `auth0` | |
79 | - uid: the user identifier | |
80 | - info: the result of the call to /userinfo using OmniAuth standard attributes | |
81 | - credentials: Auth0 tokens, at least will have an access_token but can eventually have refresh_token and/or id_token | |
82 | - extra: Additional info obtained from calling /userinfo in the attribute `raw_info` | |
53 | 83 | |
54 | 84 | ```ruby |
55 | 85 | { |
59 | 89 | :name => 'John Foo', |
60 | 90 | :email => 'johnfoo@example.org', |
61 | 91 | :nickname => 'john', |
62 | :first_name => 'John', | |
63 | :last_name => 'Foo', | |
64 | :location => 'en', | |
65 | 92 | :image => 'https://example.org/john.jpg' |
66 | 93 | }, |
67 | 94 | :credentials => { |
68 | 95 | :token => 'XdDadllcas2134rdfdsI', |
69 | :expires => 'false', | |
96 | :expires_at => 1485373937, | |
97 | :expires => true, | |
98 | :refresh_token => 'aKNajdjfj123nBasd', | |
70 | 99 | :id_token => 'eyJhbGciOiJIUzI1NiIsImN0eSI6IkpXVCJ9.eyJuYW1lIjoiSm9obiBGb28ifQ.lxAiy1rqve8ZHQEQVehUlP1sommPHVJDhgPgFPnDosg', |
71 | 100 | :token_type => 'bearer', |
72 | 101 | }, |
75 | 104 | :email => 'johnfoo@example.org', |
76 | 105 | :email_verified => 'true', |
77 | 106 | :name => 'John Foo', |
78 | :given_name => 'John', | |
79 | :family_name => 'Foo', | |
80 | 107 | :picture => 'https://example.org/john.jpg', |
81 | :gender => 'male', | |
82 | :locale => 'en', | |
83 | :clientID => 'nUBkskdaYdsaxK2n9', | |
84 | 108 | :user_id => 'google-oauth2|this-is-the-google-id', |
85 | 109 | :nickname => 'john', |
86 | :identities => [{ | |
87 | :access_token => 'this-is-the-google-access-token', | |
88 | :provider => 'google-oauth2', | |
89 | :expires_in => '3599', | |
90 | :user_id => 'this-is-the-google-id', | |
91 | :connection => 'google-oauth2', | |
92 | :isSocial => 'true', | |
93 | }], | |
94 | 110 | :created_at: '2014-07-15T17:19:50.387Z' |
95 | 111 | } |
96 | 112 | } |
119 | 135 | |
120 | 136 | ## Author |
121 | 137 | |
122 | [Auth0](auth0.com) | |
138 | [Auth0](https://auth0.com) | |
123 | 139 | |
124 | 140 | ## License |
125 | 141 |
0 | 0 | #!/usr/bin/env rake |
1 | require "bundler/gem_tasks" | |
1 | require 'bundler/gem_tasks' | |
2 | 2 | require 'rspec/core/rake_task' |
3 | 3 | |
4 | desc "Run specs" | |
4 | desc 'Run specs' | |
5 | 5 | RSpec::Core::RakeTask.new |
6 | 6 | |
7 | begin | |
8 | require 'rubocop/rake_task' | |
9 | RuboCop::RakeTask.new | |
10 | rescue LoadError | |
11 | task :rubocop do | |
12 | $stderr.puts 'Rubocop is disabled' | |
13 | end | |
14 | end | |
15 | ||
16 | namespace :sinatra do | |
17 | task :start do | |
18 | system 'bundle exec shotgun' \ | |
19 | ' --server=thin --port=3000' \ | |
20 | ' examples/sinatra/config.ru' | |
21 | end | |
22 | end | |
23 | ||
7 | 24 | desc 'Run specs' |
8 | task :default => :spec | |
9 | task :test => :spec⏎ | |
25 | task default: [:spec, :rubocop] | |
26 | task test: :spec | |
27 | task :guard do | |
28 | system 'bundle exec guard' | |
29 | end |
0 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. | |
1 | # | |
2 | # If you find yourself ignoring temporary files generated by your text editor | |
3 | # or operating system, you probably want to add a global ignore instead: | |
4 | # git config --global core.excludesfile '~/.gitignore_global' | |
5 | ||
6 | # Ignore bundler config. | |
7 | /.bundle | |
8 | ||
9 | # Ignore the default SQLite database. | |
10 | /db/*.sqlite3 | |
11 | /db/*.sqlite3-journal | |
12 | ||
13 | # Ignore all logfiles and tempfiles. | |
14 | /log/*.log | |
15 | /tmp | |
16 | .env |
0 | source 'https://rubygems.org' | |
1 | ||
2 | ||
3 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' | |
4 | gem 'rails', '4.1.1' | |
5 | # Use sqlite3 as the database for Active Record | |
6 | gem 'sqlite3', group: :development | |
7 | gem 'pry', group: :development | |
8 | gem 'pg' | |
9 | # Use SCSS for stylesheets | |
10 | gem 'sass-rails', '~> 4.0.3' | |
11 | # Use Uglifier as compressor for JavaScript assets | |
12 | gem 'uglifier', '>= 1.3.0' | |
13 | # Use CoffeeScript for .js.coffee assets and views | |
14 | gem 'coffee-rails', '~> 4.0.0' | |
15 | # See https://github.com/sstephenson/execjs#readme for more supported runtimes | |
16 | # gem 'therubyracer', platforms: :ruby | |
17 | ||
18 | gem 'rails_12factor', group: :production | |
19 | ||
20 | # Use jquery as the JavaScript library | |
21 | gem 'jquery-rails' | |
22 | # Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks | |
23 | gem 'turbolinks' | |
24 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder | |
25 | gem 'jbuilder', '~> 2.0' | |
26 | # bundle exec rake doc:rails generates the API under doc/api. | |
27 | gem 'sdoc', '~> 0.4.0', group: :doc | |
28 | ||
29 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring | |
30 | gem 'spring', group: :development | |
31 | ||
32 | gem 'omniauth', '~> 1.2' | |
33 | gem 'omniauth-auth0', '~> 1.1' | |
34 | ||
35 | gem 'dotenv', '~> 0.11.1', group: :development | |
36 | ||
37 | # Use ActiveModel has_secure_password | |
38 | # gem 'bcrypt', '~> 3.1.7' | |
39 | ||
40 | # Use unicorn as the app server | |
41 | # gem 'unicorn' | |
42 | ||
43 | # Use Capistrano for deployment | |
44 | # gem 'capistrano-rails', group: :development | |
45 | ||
46 | # Use debugger | |
47 | # gem 'debugger', group: [:development, :test] |
0 | #Auth0 + Ruby on Rails WebApp Seed | |
1 | This is the seed project you need to use if you're going to create a regular WebApp with Ruby on Rails. If you want to build a Ruby On Rails API that will be used with a SPA or a Mobile device, please check this [other seed project](https://github.com/auth0/auth0-ruby-samples/tree/master/ruby-on-rails-api) | |
2 | ||
3 | This example is deployed at Heroku at http://auth0-ror-webapp-sample.herokuapp.com/ | |
4 | ||
5 | #Running the example | |
6 | In order to run the example you need to have ruby installed. | |
7 | ||
8 | You also need to set the ClientSecret, ClientId, Domain and CallbackURL for your Auth0 app as enviroment variables with the following names respectively: AUTH0_CLIENT_SECRET, AUTH0_CLIENT_ID, AUTH0_DOMAIN and AUTH0_CALLBACK_URL. | |
9 | ||
10 | For that, if you just create a file named .env in the directory and set the values like the following, the app will just work: | |
11 | ||
12 | ````bash | |
13 | # .env file | |
14 | AUTH0_CLIENT_SECRET=myCoolSecret | |
15 | AUTH0_CLIENT_ID=myCoolClientId | |
16 | AUTH0_DOMAIN=samples.auth0.com | |
17 | AUTH0_CALLBACK_URL=http://localhost:3000/auth/auth0/callback | |
18 | ```` | |
19 | Once you've set those 4 enviroment variables, just run `rails s` and try calling [http://localhost:3000/](http://localhost:3000/) |
0 | == README | |
1 | ||
2 | This README would normally document whatever steps are necessary to get the | |
3 | application up and running. | |
4 | ||
5 | Things you may want to cover: | |
6 | ||
7 | * Ruby version | |
8 | ||
9 | * System dependencies | |
10 | ||
11 | * Configuration | |
12 | ||
13 | * Database creation | |
14 | ||
15 | * Database initialization | |
16 | ||
17 | * How to run the test suite | |
18 | ||
19 | * Services (job queues, cache servers, search engines, etc.) | |
20 | ||
21 | * Deployment instructions | |
22 | ||
23 | * ... | |
24 | ||
25 | ||
26 | Please feel free to use a different markup language if you do not plan to run | |
27 | <tt>rake doc:app</tt>. |
0 | # Add your own tasks in files placed in lib/tasks ending in .rake, | |
1 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. | |
2 | ||
3 | require File.expand_path('../config/application', __FILE__) | |
4 | ||
5 | Rails.application.load_tasks |
0 | // This is a manifest file that'll be compiled into application.js, which will include all the files | |
1 | // listed below. | |
2 | // | |
3 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, | |
4 | // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path. | |
5 | // | |
6 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the | |
7 | // compiled file. | |
8 | // | |
9 | // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details | |
10 | // about supported directives. | |
11 | // | |
12 | //= require_tree . |
0 | var lock = new Auth0Lock('<%= Rails.application.secrets.auth0_client_id %>', '<%= Rails.application.secrets.auth0_domain %>'); | |
1 | function signin() { | |
2 | lock.show({ | |
3 | callbackURL: 'http://localhost:3000/auth/auth0/callback', // use this in production '<%= Rails.application.secrets.auth0_callback_url %>' | |
4 | responseType: 'code', | |
5 | authParams: { | |
6 | scope: 'openid name email picture' | |
7 | } | |
8 | }); | |
9 | } |
0 | /* | |
1 | * This is a manifest file that'll be compiled into application.css, which will include all the files | |
2 | * listed below. | |
3 | * | |
4 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, | |
5 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. | |
6 | * | |
7 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the | |
8 | * compiled file so the styles you add here take precedence over styles defined in any styles | |
9 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new | |
10 | * file per style scope. | |
11 | * | |
12 | *= require_tree . | |
13 | *= require_self | |
14 | */ | |
15 | ||
16 | body { | |
17 | font-family: "proxima-nova", sans-serif; | |
18 | text-align: center; | |
19 | font-size: 300%; | |
20 | font-weight: 100; | |
21 | } | |
22 | input[type=checkbox], | |
23 | input[type=radio] { | |
24 | position: absolute; | |
25 | opacity: 0; | |
26 | } | |
27 | input[type=checkbox] + label, | |
28 | input[type=radio] + label { | |
29 | display: inline-block; | |
30 | } | |
31 | input[type=checkbox] + label:before, | |
32 | input[type=radio] + label:before { | |
33 | content: ""; | |
34 | display: inline-block; | |
35 | vertical-align: -0.2em; | |
36 | width: 1em; | |
37 | height: 1em; | |
38 | border: 0.15em solid #0074d9; | |
39 | border-radius: 0.2em; | |
40 | margin-right: 0.3em; | |
41 | background-color: white; | |
42 | } | |
43 | input[type=radio] + label:before { | |
44 | border-radius: 50%; | |
45 | } | |
46 | input[type=radio]:checked + label:before, | |
47 | input[type=checkbox]:checked + label:before { | |
48 | background-color: #0074d9; | |
49 | box-shadow: inset 0 0 0 0.15em white; | |
50 | } | |
51 | input[type=radio]:focus + label:before, | |
52 | input[type=checkbox]:focus + label:before { | |
53 | outline: 0; | |
54 | } | |
55 | .btn { | |
56 | font-size: 140%; | |
57 | text-transform: uppercase; | |
58 | letter-spacing: 1px; | |
59 | border: 0; | |
60 | background-color: #16214D; | |
61 | color: white; | |
62 | } | |
63 | .btn:hover { | |
64 | background-color: #44C7F4; | |
65 | } | |
66 | .btn:focus { | |
67 | outline: none !important; | |
68 | } | |
69 | .btn.btn-lg { | |
70 | padding: 20px 30px; | |
71 | } | |
72 | .btn:disabled { | |
73 | background-color: #333; | |
74 | color: #666; | |
75 | } | |
76 | h1, | |
77 | h2, | |
78 | h3 { | |
79 | font-weight: 100; | |
80 | } | |
81 | #logo img { | |
82 | width: 300px; | |
83 | margin-bottom: 60px; | |
84 | } | |
85 | .home-description { | |
86 | font-weight: 100; | |
87 | margin: 100px 0; | |
88 | } | |
89 | h2 { | |
90 | margin-top: 30px; | |
91 | margin-bottom: 40px; | |
92 | font-size: 200%; | |
93 | } | |
94 | label { | |
95 | font-size: 100%; | |
96 | font-weight: 300; | |
97 | } | |
98 | .btn-next { | |
99 | margin-top: 30px; | |
100 | } | |
101 | .answer { | |
102 | width: 70%; | |
103 | margin: auto; | |
104 | text-align: left; | |
105 | padding-left: 10%; | |
106 | margin-bottom: 20px; | |
107 | } | |
108 | .login-page .login-box { | |
109 | padding: 100px 0; | |
110 | } | |
111 | pre { | |
112 | text-align: left; | |
113 | } |
0 | class ApplicationController < ActionController::Base | |
1 | # Prevent CSRF attacks by raising an exception. | |
2 | # For APIs, you may want to use :null_session instead. | |
3 | protect_from_forgery with: :exception | |
4 | end |
0 | class Auth0Controller < ApplicationController | |
1 | def callback | |
2 | # example request.env['omniauth.auth'] in https://github.com/auth0/omniauth-auth0#auth-hash | |
3 | # id_token = session[:userinfo]['credentials']['id_token'] | |
4 | # store the user profile in session and redirect to root | |
5 | session[:userinfo] = request.env['omniauth.auth'] | |
6 | ||
7 | redirect_to '/dashboard' | |
8 | end | |
9 | ||
10 | def failure | |
11 | @error_msg = request.params['message'] | |
12 | end | |
13 | end |
0 | class SecuredController < ApplicationController | |
1 | ||
2 | before_action :logged_in_using_omniauth? | |
3 | ||
4 | private | |
5 | ||
6 | def logged_in_using_omniauth? | |
7 | unless session[:userinfo].present? | |
8 | redirect_to '/' | |
9 | end | |
10 | end | |
11 | ||
12 | end |
0 | <div class="home"> | |
1 | <div class="container"> | |
2 | <div class="login-page clearfix"> | |
3 | <div class="logged-in-box auth0-box logged-in"> | |
4 | <h1 id="logo"><img src="//cdn.auth0.com/samples/auth0_logo_final_blue_RGB.png" /></h1> | |
5 | <img class="avatar" src="<%= @user[:info][:image] %>"/> | |
6 | <h2>Welcome <%= @user[:info][:name] %></h2> | |
7 | <pre><%= JSON.pretty_generate(@user[:info]) %></pre> | |
8 | </div> | |
9 | </div> | |
10 | </div> | |
11 | </div> |
0 | <% content_for :cdn_code do %> | |
1 | <%= javascript_include_tag '//cdn.auth0.com/js/lock-7.0.min.js' %> | |
2 | <% end %> | |
3 | <div class="home"> | |
4 | <div class="container"> | |
5 | <div class="login-page clearfix"> | |
6 | <div class="login-box auth0-box before"> | |
7 | <img src="https://i.cloudup.com/StzWWrY34s.png" /> | |
8 | <h3>Auth0 Example</h3> | |
9 | <p>Zero friction identity infrastructure, built for developers</p> | |
10 | <a class="btn btn-primary btn-lg btn-login btn-block" onclick="signin()">SignIn</a> | |
11 | </div> | |
12 | </div> | |
13 | </div> | |
14 | </div> | |
15 | ||
16 |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <title>RubyOnRailsWebapp</title> | |
4 | <meta name="viewport" content="width=device-width, initial-scale=1"> | |
5 | <%= yield :cdn_code %> | |
6 | <%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css' %> | |
7 | <%= stylesheet_link_tag '//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css' %> | |
8 | <%= javascript_include_tag '//use.typekit.net/iws6ohy.js' %> | |
9 | <script type="text/javascript">try{Typekit.load();}catch(e){}</script> | |
10 | ||
11 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> | |
12 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> | |
13 | <%= csrf_meta_tags %> | |
14 | </head> | |
15 | <body> | |
16 | ||
17 | <%= yield %> | |
18 | ||
19 | </body> | |
20 | </html> |
0 | #!/usr/bin/env ruby | |
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) | |
2 | load Gem.bin_path('bundler', 'bundle') |
0 | #!/usr/bin/env ruby | |
1 | APP_PATH = File.expand_path('../../config/application', __FILE__) | |
2 | require_relative '../config/boot' | |
3 | require 'rails/commands' |
0 | #!/usr/bin/env ruby | |
1 | ||
2 | # This file loads spring without using Bundler, in order to be fast | |
3 | # It gets overwritten when you run the `spring binstub` command | |
4 | ||
5 | unless defined?(Spring) | |
6 | require "rubygems" | |
7 | require "bundler" | |
8 | ||
9 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m) | |
10 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) | |
11 | ENV["GEM_HOME"] = "" | |
12 | Gem.paths = ENV | |
13 | ||
14 | gem "spring", match[1] | |
15 | require "spring/binstub" | |
16 | end | |
17 | end |
0 | require File.expand_path('../boot', __FILE__) | |
1 | ||
2 | require 'rails/all' | |
3 | ||
4 | # Require the gems listed in Gemfile, including any gems | |
5 | # you've limited to :test, :development, or :production. | |
6 | Bundler.require(*Rails.groups) | |
7 | ||
8 | module RubyOnRailsWebapp | |
9 | class Application < Rails::Application | |
10 | ||
11 | ||
12 | # Set this if you want to get the error_description | |
13 | # OmniAuth.config.on_failure = Proc.new { |env| | |
14 | # message_key = env['omniauth.error.type'] | |
15 | # error_description = Rack::Utils.escape(env['omniauth.error'].error_reason) | |
16 | # new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}&error_description=#{error_description}" | |
17 | # Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish | |
18 | # } | |
19 | # Settings in config/environments/* take precedence over those specified here. | |
20 | # Application configuration should go into files in config/initializers | |
21 | # -- all .rb files in that directory are automatically loaded. | |
22 | ||
23 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. | |
24 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. | |
25 | # config.time_zone = 'Central Time (US & Canada)' | |
26 | ||
27 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. | |
28 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] | |
29 | # config.i18n.default_locale = :de | |
30 | end | |
31 | end |
0 | # Set up gems listed in the Gemfile. | |
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) | |
2 | ||
3 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) |
0 | development: | |
1 | adapter: sqlite3 | |
2 | pool: 5 | |
3 | timeout: 5000 | |
4 | database: db/development.sqlite3 | |
5 | ||
6 | # Warning: The database defined as "test" will be erased and | |
7 | # re-generated from your development database when you run "rake". | |
8 | # Do not set this db to the same as development or production. | |
9 | test: | |
10 | adapter: sqlite3 | |
11 | pool: 5 | |
12 | timeout: 5000 | |
13 | database: db/development.sqlite3 | |
14 | ||
15 | production: | |
16 | adapter: postgresql | |
17 | database: my_database_production | |
18 | pool: 5 | |
19 | timeout: 5000 |
0 | # Load the Rails application. | |
1 | require File.expand_path('../application', __FILE__) | |
2 | ||
3 | # Initialize the Rails application. | |
4 | Rails.application.initialize! |
0 | Rails.application.configure do | |
1 | # Settings specified here will take precedence over those in config/application.rb. | |
2 | ||
3 | # In the development environment your application's code is reloaded on | |
4 | # every request. This slows down response time but is perfect for development | |
5 | # since you don't have to restart the web server when you make code changes. | |
6 | config.cache_classes = false | |
7 | ||
8 | config.cachestore = :memorystore | |
9 | ||
10 | # Do not eager load code on boot. | |
11 | config.eager_load = false | |
12 | ||
13 | # Show full error reports and disable caching. | |
14 | config.consider_all_requests_local = true | |
15 | config.action_controller.perform_caching = false | |
16 | ||
17 | # Don't care if the mailer can't send. | |
18 | config.action_mailer.raise_delivery_errors = false | |
19 | ||
20 | # Print deprecation notices to the Rails logger. | |
21 | config.active_support.deprecation = :log | |
22 | ||
23 | # Raise an error on page load if there are pending migrations. | |
24 | config.active_record.migration_error = :page_load | |
25 | ||
26 | # Debug mode disables concatenation and preprocessing of assets. | |
27 | # This option may cause significant delays in view rendering with a large | |
28 | # number of complex assets. | |
29 | config.assets.debug = true | |
30 | ||
31 | # Adds additional error checking when serving assets at runtime. | |
32 | # Checks for improperly declared sprockets dependencies. | |
33 | # Raises helpful error messages. | |
34 | config.assets.raise_runtime_errors = true | |
35 | ||
36 | # Raises error for missing translations | |
37 | # config.action_view.raise_on_missing_translations = true | |
38 | end |
0 | Rails.application.configure do | |
1 | # Settings specified here will take precedence over those in config/application.rb. | |
2 | ||
3 | # Code is not reloaded between requests. | |
4 | config.cache_classes = true | |
5 | ||
6 | # Eager load code on boot. This eager loads most of Rails and | |
7 | # your application in memory, allowing both threaded web servers | |
8 | # and those relying on copy on write to perform better. | |
9 | # Rake tasks automatically ignore this option for performance. | |
10 | config.eager_load = true | |
11 | ||
12 | # Full error reports are disabled and caching is turned on. | |
13 | config.consider_all_requests_local = false | |
14 | config.action_controller.perform_caching = true | |
15 | ||
16 | # Enable Rack::Cache to put a simple HTTP cache in front of your application | |
17 | # Add `rack-cache` to your Gemfile before enabling this. | |
18 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. | |
19 | # config.action_dispatch.rack_cache = true | |
20 | ||
21 | # Disable Rails's static asset server (Apache or nginx will already do this). | |
22 | config.serve_static_assets = false | |
23 | ||
24 | # Compress JavaScripts and CSS. | |
25 | config.assets.js_compressor = :uglifier | |
26 | # config.assets.css_compressor = :sass | |
27 | ||
28 | # Do not fallback to assets pipeline if a precompiled asset is missed. | |
29 | config.assets.compile = false | |
30 | ||
31 | # Generate digests for assets URLs. | |
32 | config.assets.digest = true | |
33 | ||
34 | # Version of your assets, change this if you want to expire all your assets. | |
35 | config.assets.version = '1.0' | |
36 | ||
37 | # Specifies the header that your server uses for sending files. | |
38 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache | |
39 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx | |
40 | ||
41 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. | |
42 | # config.force_ssl = true | |
43 | ||
44 | # Set to :debug to see everything in the log. | |
45 | config.log_level = :info | |
46 | ||
47 | # Prepend all log lines with the following tags. | |
48 | # config.log_tags = [ :subdomain, :uuid ] | |
49 | ||
50 | # Use a different logger for distributed setups. | |
51 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) | |
52 | ||
53 | # Use a different cache store in production. | |
54 | # config.cache_store = :mem_cache_store | |
55 | ||
56 | config.cachestore = :memorystore | |
57 | ||
58 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. | |
59 | # config.action_controller.asset_host = "http://assets.example.com" | |
60 | ||
61 | # Precompile additional assets. | |
62 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. | |
63 | # config.assets.precompile += %w( search.js ) | |
64 | ||
65 | # Ignore bad email addresses and do not raise email delivery errors. | |
66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. | |
67 | # config.action_mailer.raise_delivery_errors = false | |
68 | ||
69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to | |
70 | # the I18n.default_locale when a translation cannot be found). | |
71 | config.i18n.fallbacks = true | |
72 | ||
73 | # Send deprecation notices to registered listeners. | |
74 | config.active_support.deprecation = :notify | |
75 | ||
76 | # Disable automatic flushing of the log to improve performance. | |
77 | # config.autoflush_log = false | |
78 | ||
79 | # Use default logging formatter so that PID and timestamp are not suppressed. | |
80 | config.log_formatter = ::Logger::Formatter.new | |
81 | ||
82 | # Do not dump schema after migrations. | |
83 | config.active_record.dump_schema_after_migration = false | |
84 | end |
0 | Rails.application.configure do | |
1 | # Settings specified here will take precedence over those in config/application.rb. | |
2 | ||
3 | # The test environment is used exclusively to run your application's | |
4 | # test suite. You never need to work with it otherwise. Remember that | |
5 | # your test database is "scratch space" for the test suite and is wiped | |
6 | # and recreated between test runs. Don't rely on the data there! | |
7 | config.cache_classes = true | |
8 | ||
9 | # Do not eager load code on boot. This avoids loading your whole application | |
10 | # just for the purpose of running a single test. If you are using a tool that | |
11 | # preloads Rails for running tests, you may have to set it to true. | |
12 | config.eager_load = false | |
13 | ||
14 | # Configure static asset server for tests with Cache-Control for performance. | |
15 | config.serve_static_assets = true | |
16 | config.static_cache_control = 'public, max-age=3600' | |
17 | ||
18 | # Show full error reports and disable caching. | |
19 | config.consider_all_requests_local = true | |
20 | config.action_controller.perform_caching = false | |
21 | ||
22 | # Raise exceptions instead of rendering exception templates. | |
23 | config.action_dispatch.show_exceptions = false | |
24 | ||
25 | # Disable request forgery protection in test environment. | |
26 | config.action_controller.allow_forgery_protection = false | |
27 | ||
28 | # Tell Action Mailer not to deliver emails to the real world. | |
29 | # The :test delivery method accumulates sent emails in the | |
30 | # ActionMailer::Base.deliveries array. | |
31 | config.action_mailer.delivery_method = :test | |
32 | ||
33 | # Print deprecation notices to the stderr. | |
34 | config.active_support.deprecation = :stderr | |
35 | ||
36 | # Raises error for missing translations | |
37 | # config.action_view.raise_on_missing_translations = true | |
38 | end |
0 | Rails.application.config.middleware.use OmniAuth::Builder do | |
1 | provider( | |
2 | :auth0, | |
3 | ENV["AUTH0_CLIENT_ID"], | |
4 | ENV["AUTH0_CLIENT_SECRET"], | |
5 | ENV["AUTH0_DOMAIN"], | |
6 | callback_path: "/auth/auth0/callback" | |
7 | ) | |
8 | end |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. | |
3 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } | |
4 | ||
5 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. | |
6 | # Rails.backtrace_cleaner.remove_silencers! |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | Rails.application.config.action_dispatch.cookies_serializer = :json⏎ |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # Configure sensitive parameters which will be filtered from the log file. | |
3 | Rails.application.config.filter_parameters += [:password] |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # Add new inflection rules using the following format. Inflections | |
3 | # are locale specific, and you may define rules for as many different | |
4 | # locales as you wish. All of these examples are active by default: | |
5 | # ActiveSupport::Inflector.inflections(:en) do |inflect| | |
6 | # inflect.plural /^(ox)$/i, '\1en' | |
7 | # inflect.singular /^(ox)en/i, '\1' | |
8 | # inflect.irregular 'person', 'people' | |
9 | # inflect.uncountable %w( fish sheep ) | |
10 | # end | |
11 | ||
12 | # These inflection rules are supported but not enabled by default: | |
13 | # ActiveSupport::Inflector.inflections(:en) do |inflect| | |
14 | # inflect.acronym 'RESTful' | |
15 | # end |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # Add new mime types for use in respond_to blocks: | |
3 | # Mime::Type.register "text/richtext", :rtf |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | Rails.application.config.session_store :cache_store |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # This file contains settings for ActionController::ParamsWrapper which | |
3 | # is enabled by default. | |
4 | ||
5 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. | |
6 | ActiveSupport.on_load(:action_controller) do | |
7 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) | |
8 | end | |
9 | ||
10 | # To enable root element in JSON for ActiveRecord objects. | |
11 | # ActiveSupport.on_load(:active_record) do | |
12 | # self.include_root_in_json = true | |
13 | # end |
0 | # Files in the config/locales directory are used for internationalization | |
1 | # and are automatically loaded by Rails. If you want to use locales other | |
2 | # than English, add the necessary files in this directory. | |
3 | # | |
4 | # To use the locales, use `I18n.t`: | |
5 | # | |
6 | # I18n.t 'hello' | |
7 | # | |
8 | # In views, this is aliased to just `t`: | |
9 | # | |
10 | # <%= t('hello') %> | |
11 | # | |
12 | # To use a different locale, set it with `I18n.locale`: | |
13 | # | |
14 | # I18n.locale = :es | |
15 | # | |
16 | # This would use the information in config/locales/es.yml. | |
17 | # | |
18 | # To learn more, please read the Rails Internationalization guide | |
19 | # available at http://guides.rubyonrails.org/i18n.html. | |
20 | ||
21 | en: | |
22 | hello: "Hello world" |
0 | Rails.application.routes.draw do | |
1 | ||
2 | get 'dashboard/show' | |
3 | ||
4 | get "/" => "home#show" | |
5 | ||
6 | get "/dashboard" => "dashboard#show" | |
7 | ||
8 | get "/auth/auth0/callback" => "auth0#callback" | |
9 | get "/auth/failure" => "auth0#failure" | |
10 | ||
11 | # The priority is based upon order of creation: first created -> highest priority. | |
12 | # See how all your routes lay out with "rake routes". | |
13 | ||
14 | # You can have the root of your site routed with "root" | |
15 | # root 'welcome#index' | |
16 | ||
17 | # Example of regular route: | |
18 | # get 'products/:id' => 'catalog#view' | |
19 | ||
20 | # Example of named route that can be invoked with purchase_url(id: product.id) | |
21 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase | |
22 | ||
23 | # Example resource route (maps HTTP verbs to controller actions automatically): | |
24 | # resources :products | |
25 | ||
26 | # Example resource route with options: | |
27 | # resources :products do | |
28 | # member do | |
29 | # get 'short' | |
30 | # post 'toggle' | |
31 | # end | |
32 | # | |
33 | # collection do | |
34 | # get 'sold' | |
35 | # end | |
36 | # end | |
37 | ||
38 | # Example resource route with sub-resources: | |
39 | # resources :products do | |
40 | # resources :comments, :sales | |
41 | # resource :seller | |
42 | # end | |
43 | ||
44 | # Example resource route with more complex sub-resources: | |
45 | # resources :products do | |
46 | # resources :comments | |
47 | # resources :sales do | |
48 | # get 'recent', on: :collection | |
49 | # end | |
50 | # end | |
51 | ||
52 | # Example resource route with concerns: | |
53 | # concern :toggleable do | |
54 | # post 'toggle' | |
55 | # end | |
56 | # resources :posts, concerns: :toggleable | |
57 | # resources :photos, concerns: :toggleable | |
58 | ||
59 | # Example resource route within a namespace: | |
60 | # namespace :admin do | |
61 | # # Directs /admin/products/* to Admin::ProductsController | |
62 | # # (app/controllers/admin/products_controller.rb) | |
63 | # resources :products | |
64 | # end | |
65 | end |
0 | # Be sure to restart your server when you modify this file. | |
1 | ||
2 | # Your secret key is used for verifying the integrity of signed cookies. | |
3 | # If you change this key, all old signed cookies will become invalid! | |
4 | ||
5 | # Make sure the secret is at least 30 characters and all random, | |
6 | # no regular words or you'll be exposed to dictionary attacks. | |
7 | # You can use `rake secret` to generate a secure secret key. | |
8 | ||
9 | # Make sure the secrets in this file are kept private | |
10 | # if you're sharing your code publicly. | |
11 | ||
12 | development: | |
13 | secret_key_base: 44943afd8bfa7c8f48302d23a56af7a44766e516fc9b2585e9b198fb55e628e1a11ff2b876f193068f23dac95031e2d36fce28341f429076fcc322df68a4c572 | |
14 | auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> | |
15 | auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> | |
16 | auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> | |
17 | auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> | |
18 | ||
19 | ||
20 | test: | |
21 | secret_key_base: 730ab4e74b6278ea9ecf8da4975ce7959836fc082b4974eb3cb65e0026be59b6502082b23fcecea9c611b5e5059632f876cdc7d5b31b3e80fc7c7b76c70e85b3 | |
22 | auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> | |
23 | auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> | |
24 | auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> | |
25 | auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> | |
26 | ||
27 | # Do not keep production secrets in the repository, | |
28 | # instead read values from the environment. | |
29 | production: | |
30 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> | |
31 | auth0_client_id: <%= ENV["AUTH0_CLIENT_ID"] %> | |
32 | auth0_client_secret: <%= ENV["AUTH0_CLIENT_SECRET"] %> | |
33 | auth0_domain: <%= ENV["AUTH0_DOMAIN"] %> | |
34 | auth0_callback_url: <%= ENV["AUTH0_CALLBACK_URL"] %> |
0 | # This file is used by Rack-based servers to start the application. | |
1 | ||
2 | require ::File.expand_path('../config/environment', __FILE__) | |
3 | run Rails.application |
0 | # This file should contain all the record creation needed to seed the database with its default values. | |
1 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). | |
2 | # | |
3 | # Examples: | |
4 | # | |
5 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) | |
6 | # Mayor.create(name: 'Emanuel', city: cities.first) |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <title>The page you were looking for doesn't exist (404)</title> | |
4 | <meta name="viewport" content="width=device-width,initial-scale=1"> | |
5 | <style> | |
6 | body { | |
7 | background-color: #EFEFEF; | |
8 | color: #2E2F30; | |
9 | text-align: center; | |
10 | font-family: arial, sans-serif; | |
11 | margin: 0; | |
12 | } | |
13 | ||
14 | div.dialog { | |
15 | width: 95%; | |
16 | max-width: 33em; | |
17 | margin: 4em auto 0; | |
18 | } | |
19 | ||
20 | div.dialog > div { | |
21 | border: 1px solid #CCC; | |
22 | border-right-color: #999; | |
23 | border-left-color: #999; | |
24 | border-bottom-color: #BBB; | |
25 | border-top: #B00100 solid 4px; | |
26 | border-top-left-radius: 9px; | |
27 | border-top-right-radius: 9px; | |
28 | background-color: white; | |
29 | padding: 7px 12% 0; | |
30 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
31 | } | |
32 | ||
33 | h1 { | |
34 | font-size: 100%; | |
35 | color: #730E15; | |
36 | line-height: 1.5em; | |
37 | } | |
38 | ||
39 | div.dialog > p { | |
40 | margin: 0 0 1em; | |
41 | padding: 1em; | |
42 | background-color: #F7F7F7; | |
43 | border: 1px solid #CCC; | |
44 | border-right-color: #999; | |
45 | border-left-color: #999; | |
46 | border-bottom-color: #999; | |
47 | border-bottom-left-radius: 4px; | |
48 | border-bottom-right-radius: 4px; | |
49 | border-top-color: #DADADA; | |
50 | color: #666; | |
51 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
52 | } | |
53 | </style> | |
54 | </head> | |
55 | ||
56 | <body> | |
57 | <!-- This file lives in public/404.html --> | |
58 | <div class="dialog"> | |
59 | <div> | |
60 | <h1>The page you were looking for doesn't exist.</h1> | |
61 | <p>You may have mistyped the address or the page may have moved.</p> | |
62 | </div> | |
63 | <p>If you are the application owner check the logs for more information.</p> | |
64 | </div> | |
65 | </body> | |
66 | </html> |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <title>The change you wanted was rejected (422)</title> | |
4 | <meta name="viewport" content="width=device-width,initial-scale=1"> | |
5 | <style> | |
6 | body { | |
7 | background-color: #EFEFEF; | |
8 | color: #2E2F30; | |
9 | text-align: center; | |
10 | font-family: arial, sans-serif; | |
11 | margin: 0; | |
12 | } | |
13 | ||
14 | div.dialog { | |
15 | width: 95%; | |
16 | max-width: 33em; | |
17 | margin: 4em auto 0; | |
18 | } | |
19 | ||
20 | div.dialog > div { | |
21 | border: 1px solid #CCC; | |
22 | border-right-color: #999; | |
23 | border-left-color: #999; | |
24 | border-bottom-color: #BBB; | |
25 | border-top: #B00100 solid 4px; | |
26 | border-top-left-radius: 9px; | |
27 | border-top-right-radius: 9px; | |
28 | background-color: white; | |
29 | padding: 7px 12% 0; | |
30 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
31 | } | |
32 | ||
33 | h1 { | |
34 | font-size: 100%; | |
35 | color: #730E15; | |
36 | line-height: 1.5em; | |
37 | } | |
38 | ||
39 | div.dialog > p { | |
40 | margin: 0 0 1em; | |
41 | padding: 1em; | |
42 | background-color: #F7F7F7; | |
43 | border: 1px solid #CCC; | |
44 | border-right-color: #999; | |
45 | border-left-color: #999; | |
46 | border-bottom-color: #999; | |
47 | border-bottom-left-radius: 4px; | |
48 | border-bottom-right-radius: 4px; | |
49 | border-top-color: #DADADA; | |
50 | color: #666; | |
51 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
52 | } | |
53 | </style> | |
54 | </head> | |
55 | ||
56 | <body> | |
57 | <!-- This file lives in public/422.html --> | |
58 | <div class="dialog"> | |
59 | <div> | |
60 | <h1>The change you wanted was rejected.</h1> | |
61 | <p>Maybe you tried to change something you didn't have access to.</p> | |
62 | </div> | |
63 | <p>If you are the application owner check the logs for more information.</p> | |
64 | </div> | |
65 | </body> | |
66 | </html> |
0 | <!DOCTYPE html> | |
1 | <html> | |
2 | <head> | |
3 | <title>We're sorry, but something went wrong (500)</title> | |
4 | <meta name="viewport" content="width=device-width,initial-scale=1"> | |
5 | <style> | |
6 | body { | |
7 | background-color: #EFEFEF; | |
8 | color: #2E2F30; | |
9 | text-align: center; | |
10 | font-family: arial, sans-serif; | |
11 | margin: 0; | |
12 | } | |
13 | ||
14 | div.dialog { | |
15 | width: 95%; | |
16 | max-width: 33em; | |
17 | margin: 4em auto 0; | |
18 | } | |
19 | ||
20 | div.dialog > div { | |
21 | border: 1px solid #CCC; | |
22 | border-right-color: #999; | |
23 | border-left-color: #999; | |
24 | border-bottom-color: #BBB; | |
25 | border-top: #B00100 solid 4px; | |
26 | border-top-left-radius: 9px; | |
27 | border-top-right-radius: 9px; | |
28 | background-color: white; | |
29 | padding: 7px 12% 0; | |
30 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
31 | } | |
32 | ||
33 | h1 { | |
34 | font-size: 100%; | |
35 | color: #730E15; | |
36 | line-height: 1.5em; | |
37 | } | |
38 | ||
39 | div.dialog > p { | |
40 | margin: 0 0 1em; | |
41 | padding: 1em; | |
42 | background-color: #F7F7F7; | |
43 | border: 1px solid #CCC; | |
44 | border-right-color: #999; | |
45 | border-left-color: #999; | |
46 | border-bottom-color: #999; | |
47 | border-bottom-left-radius: 4px; | |
48 | border-bottom-right-radius: 4px; | |
49 | border-top-color: #DADADA; | |
50 | color: #666; | |
51 | box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17); | |
52 | } | |
53 | </style> | |
54 | </head> | |
55 | ||
56 | <body> | |
57 | <!-- This file lives in public/500.html --> | |
58 | <div class="dialog"> | |
59 | <div> | |
60 | <h1>We're sorry, but something went wrong.</h1> | |
61 | </div> | |
62 | <p>If you are the application owner check the logs for more information.</p> | |
63 | </div> | |
64 | </body> | |
65 | </html> |
0 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file | |
1 | # | |
2 | # To ban all spiders from the entire site uncomment the next two lines: | |
3 | # User-agent: * | |
4 | # Disallow: / |
0 | require 'test_helper' | |
1 | ||
2 | class CallbackControllerTest < ActionController::TestCase | |
3 | test "should get store" do | |
4 | get :store | |
5 | assert_response :success | |
6 | end | |
7 | ||
8 | test "should get failure" do | |
9 | get :failure | |
10 | assert_response :success | |
11 | end | |
12 | ||
13 | end |
0 | require 'test_helper' | |
1 | ||
2 | class DashboardControllerTest < ActionController::TestCase | |
3 | test "should get show" do | |
4 | get :show | |
5 | assert_response :success | |
6 | end | |
7 | ||
8 | end |
0 | require 'test_helper' | |
1 | ||
2 | class HomeControllerTest < ActionController::TestCase | |
3 | test "should get show" do | |
4 | get :show | |
5 | assert_response :success | |
6 | end | |
7 | ||
8 | end |
0 | ENV['RAILS_ENV'] ||= 'test' | |
1 | require File.expand_path('../../config/environment', __FILE__) | |
2 | require 'rails/test_help' | |
3 | ||
4 | class ActiveSupport::TestCase | |
5 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. | |
6 | # | |
7 | # Note: You'll currently still have to declare fixtures explicitly in integration tests | |
8 | # -- they do not yet inherit this setting | |
9 | fixtures :all | |
10 | ||
11 | # Add more helper methods to be used by all tests here... | |
12 | end |
0 | require 'sinatra' | |
1 | require 'omniauth-auth0' | |
2 | require 'dotenv/load' | |
3 | ||
4 | use OmniAuth::Builder do | |
5 | provider :auth0, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'], ENV['DOMAIN'] | |
6 | end | |
7 | ||
8 | enable :sessions | |
9 | set :session_secret, ENV['SESSION_SECRET'] | |
10 | ||
11 | get '/' do | |
12 | 'Auth0 OmniAuth Example for Sinatra' | |
13 | end |
0 | require "base64" | |
1 | require "omniauth-oauth2" | |
0 | require 'base64' | |
1 | require 'uri' | |
2 | require 'omniauth-oauth2' | |
2 | 3 | |
3 | 4 | module OmniAuth |
4 | 5 | module Strategies |
6 | # Auth0 OmniAuth strategy | |
5 | 7 | class Auth0 < OmniAuth::Strategies::OAuth2 |
6 | PASSTHROUGHS = %w[ | |
7 | connection | |
8 | redirect_uri | |
8 | option :name, 'auth0' | |
9 | ||
10 | args [ | |
11 | :client_id, | |
12 | :client_secret, | |
13 | :domain | |
9 | 14 | ] |
10 | 15 | |
11 | option :name, "auth0" | |
12 | option :namespace, nil | |
13 | option :provider_ignores_state, true | |
14 | option :connection | |
15 | ||
16 | args [:client_id, :client_secret, :namespace, :provider_ignores_state, :connection] | |
17 | ||
18 | def initialize(app, *args, &block) | |
16 | def client | |
17 | options.client_options.site = domain_url | |
18 | options.client_options.authorize_url = '/authorize' | |
19 | options.client_options.token_url = '/oauth/token' | |
20 | options.client_options.userinfo_url = '/userinfo' | |
19 | 21 | super |
20 | fail(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) if @options[:namespace].nil? | |
21 | ||
22 | @options.provider_ignores_state = args[3] unless args[3].nil? | |
23 | @options.connection = args[4] unless args[4].nil? | |
24 | ||
25 | @options.client_options.site = "https://#{options[:namespace]}" | |
26 | @options.client_options.authorize_url = "https://#{options[:namespace]}/authorize?#{client_info_querystring}" | |
27 | @options.client_options.token_url = "https://#{options[:namespace]}/oauth/token?#{client_info_querystring}" | |
28 | @options.client_options.userinfo_url = "https://#{options[:namespace]}/userinfo" | |
29 | 22 | end |
30 | 23 | |
31 | def authorize_params | |
32 | super.tap do |param| | |
33 | PASSTHROUGHS.each do |p| | |
34 | param[p.to_sym] = request.params[p] if request.params[p] | |
35 | end | |
36 | if @options.connection | |
37 | param[:connection] = @options.connection | |
38 | end | |
39 | end | |
40 | end | |
24 | uid { raw_info['sub'] } | |
41 | 25 | |
42 | 26 | credentials do |
43 | hash = {'token' => access_token.token} | |
44 | hash.merge!('expires' => true) | |
27 | hash = { 'token' => access_token.token } | |
28 | hash['expires'] = true | |
45 | 29 | if access_token.params |
46 | hash.merge!('id_token' => access_token.params['id_token']) | |
47 | hash.merge!('token_type' => access_token.params['token_type']) | |
48 | hash.merge!('refresh_token' => access_token.refresh_token) if access_token.refresh_token | |
30 | hash['id_token'] = access_token.params['id_token'] | |
31 | hash['token_type'] = access_token.params['token_type'] | |
32 | hash['refresh_token'] = access_token.refresh_token | |
49 | 33 | end |
50 | 34 | hash |
51 | 35 | end |
52 | 36 | |
53 | uid { raw_info["user_id"] } | |
54 | ||
55 | 37 | extra do |
56 | { :raw_info => raw_info } | |
38 | { | |
39 | raw_info: raw_info | |
40 | } | |
57 | 41 | end |
58 | 42 | |
59 | 43 | info do |
60 | 44 | { |
61 | :name => raw_info["name"], | |
62 | :email => raw_info["email"], | |
63 | :nickname => raw_info["nickname"], | |
64 | :first_name => raw_info["given_name"], | |
65 | :last_name => raw_info["family_name"], | |
66 | :location => raw_info["locale"], | |
67 | :image => raw_info["picture"] | |
45 | name: raw_info['name'] || raw_info['sub'], | |
46 | nickname: raw_info['nickname'], | |
47 | email: raw_info['email'], | |
48 | image: raw_info['picture'] | |
68 | 49 | } |
69 | 50 | end |
70 | 51 | |
71 | def raw_info | |
72 | @raw_info ||= access_token.get(options.client_options.userinfo_url).parsed | |
52 | def authorize_params | |
53 | params = super | |
54 | params['auth0Client'] = client_info | |
55 | params | |
56 | end | |
57 | ||
58 | def request_phase | |
59 | if no_client_id? | |
60 | fail!(:missing_client_id) | |
61 | elsif no_client_secret? | |
62 | fail!(:missing_client_secret) | |
63 | elsif no_domain? | |
64 | fail!(:missing_domain) | |
65 | else | |
66 | super | |
67 | end | |
73 | 68 | end |
74 | 69 | |
75 | 70 | private |
76 | def client_info_querystring | |
77 | client_info = JSON.dump({name: 'omniauth-auth0', version: OmniAuth::Auth0::VERSION}) | |
78 | "auth0Client=" + Base64.urlsafe_encode64(client_info) | |
71 | ||
72 | def raw_info | |
73 | userinfo_url = options.client_options.userinfo_url | |
74 | @raw_info ||= access_token.get(userinfo_url).parsed | |
75 | end | |
76 | ||
77 | def no_client_id? | |
78 | ['', nil].include?(options.client_id) | |
79 | end | |
80 | ||
81 | def no_client_secret? | |
82 | ['', nil].include?(options.client_secret) | |
83 | end | |
84 | ||
85 | def no_domain? | |
86 | ['', nil].include?(options.domain) | |
87 | end | |
88 | ||
89 | def domain_url | |
90 | domain_url = URI(options.domain) | |
91 | domain_url = URI("https://#{domain_url}") if domain_url.scheme.nil? | |
92 | domain_url.to_s | |
93 | end | |
94 | ||
95 | def client_info | |
96 | client_info = JSON.dump( | |
97 | name: 'omniauth-auth0', | |
98 | version: OmniAuth::Auth0::VERSION | |
99 | ) | |
100 | Base64.urlsafe_encode64(client_info) | |
79 | 101 | end |
80 | 102 | end |
81 | 103 | end |
0 | require "omniauth-auth0/version" | |
1 | require "omniauth/strategies/auth0"⏎ | |
0 | require 'omniauth-auth0/version' # rubocop:disable Style/FileName | |
1 | require 'omniauth/strategies/auth0' |
0 | 0 | # -*- encoding: utf-8 -*- |
1 | $:.push File.expand_path("../lib", __FILE__) | |
2 | require "omniauth-auth0/version" | |
1 | $LOAD_PATH.push File.expand_path('../lib', __FILE__) | |
2 | require 'omniauth-auth0/version' | |
3 | 3 | |
4 | 4 | Gem::Specification.new do |s| |
5 | s.name = "omniauth-auth0" | |
5 | s.name = 'omniauth-auth0' | |
6 | 6 | s.version = OmniAuth::Auth0::VERSION |
7 | s.authors = ["Auth0", "Ezequiel Morito", "Jose Romaniello"] | |
8 | s.email = ["support@auth0.com"] | |
9 | s.homepage = "https://github.com/auth0/omniauth-auth0" | |
10 | s.summary = %q{Omniauth OAuth2 strategy for the Auth0 platform.} | |
7 | s.authors = ['Auth0'] | |
8 | s.email = ['info@auth0.com'] | |
9 | s.homepage = 'https://github.com/auth0/omniauth-auth0' | |
10 | s.summary = 'Omniauth OAuth2 strategy for the Auth0 platform.' | |
11 | 11 | 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. |
12 | 12 | |
13 | 13 | 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. |
15 | 15 | omniauth-auth0 is the omniauth strategy for Auth0. |
16 | 16 | } |
17 | 17 | |
18 | s.rubyforge_project = "omniauth-auth0" | |
18 | s.rubyforge_project = 'omniauth-auth0' | |
19 | 19 | |
20 | 20 | s.files = `git ls-files`.split("\n") |
21 | 21 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") |
22 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } | |
23 | s.require_paths = ["lib"] | |
22 | s.executables = `git ls-files -- bin/*`.split('\n').map{ |f| File.basename(f) } | |
23 | s.require_paths = ['lib'] | |
24 | 24 | |
25 | s.add_runtime_dependency 'omniauth-oauth2', '~> 1.1' | |
25 | s.add_runtime_dependency 'omniauth-oauth2', '~> 1.4' | |
26 | 26 | |
27 | s.add_development_dependency 'rspec', '~> 2.7' | |
28 | s.add_development_dependency 'rack-test', '~> 0.6', '>= 0.6.3' | |
29 | s.add_development_dependency 'simplecov', '~> 0.9', '>= 0.9.1' | |
30 | s.add_development_dependency 'webmock', '~> 1.20', '>= 1.20.4' | |
31 | s.add_development_dependency 'rake', '~> 10.3', '>= 10.3.2' | |
32 | s.add_development_dependency 'gem-release', '~> 0.7' | |
27 | s.add_development_dependency 'bundler', '~> 1.9' | |
33 | 28 | |
34 | 29 | s.license = 'MIT' |
35 | 30 | end |
0 | require "spec_helper" | |
0 | require 'spec_helper' | |
1 | ||
2 | RSpec.shared_examples 'site has valid domain url' do |url| | |
3 | it { expect(subject.site).to eq(url) } | |
4 | end | |
1 | 5 | |
2 | 6 | describe OmniAuth::Strategies::Auth0 do |
3 | let(:app){ Rack::Builder.new do |b| | |
4 | b.use Rack::Session::Cookie, {:secret => "abc123"} | |
5 | b.run lambda{|env| [200, {}, ['Not Found']]} | |
6 | end.to_app } | |
7 | ||
8 | before :each do | |
9 | OmniAuth.config.test_mode = true | |
10 | @request = double('Request') | |
11 | allow(@request).to receive(:params) | |
12 | allow(@request).to receive(:cookies) | |
13 | allow(@request).to receive(:env) | |
14 | ||
15 | @session = double('Session') | |
16 | allow(@session).to receive(:delete).with('omniauth.state').and_return('state') | |
17 | end | |
18 | ||
19 | after do | |
20 | OmniAuth.config.test_mode = false | |
21 | end | |
22 | ||
23 | subject do | |
24 | OmniAuth::Strategies::Auth0.new(app, | |
25 | "client_id", "client_secret", "tenny.auth0.com:3000").tap do |strategy| | |
26 | allow(strategy).to receive(:request) { @request } | |
27 | end | |
28 | end | |
29 | ||
30 | context "initiation" do | |
31 | let(:base64_token) { | |
32 | Base64.urlsafe_encode64('{"name":"omniauth-auth0","version":"' + OmniAuth::Auth0::VERSION + '"}') | |
33 | } | |
34 | ||
35 | it "uses the correct site" do | |
36 | expect(subject.options.client_options.site).to eql "https://tenny.auth0.com:3000" | |
37 | end | |
38 | ||
39 | it "uses the correct authorize_url" do | |
40 | expect(subject.options.client_options.authorize_url). | |
41 | to eql "https://tenny.auth0.com:3000/authorize?auth0Client=#{base64_token}" | |
42 | ||
43 | end | |
44 | ||
45 | it "uses the correct token_url" do | |
46 | expect(subject.options.client_options.token_url). | |
47 | to eql "https://tenny.auth0.com:3000/oauth/token?auth0Client=#{base64_token}" | |
48 | end | |
49 | ||
50 | it "uses the correct userinfo url" do | |
51 | expect(subject.options.client_options.userinfo_url). | |
52 | to eql "https://tenny.auth0.com:3000/userinfo" | |
53 | end | |
54 | ||
55 | it "should raise an ArgumentError error if no namespace passed" do | |
56 | expect { | |
57 | OmniAuth::Strategies::Auth0.new(app, "client_id", "client_secret") | |
58 | }.to raise_error(ArgumentError) | |
59 | end | |
60 | end | |
61 | ||
62 | context "request phase" do | |
63 | before(:each){ get '/auth/auth0' } | |
64 | ||
65 | it "authenticate" do | |
66 | expect(last_response.status).to eq(200) | |
67 | end | |
68 | ||
69 | it "authorize params" do | |
70 | allow(subject).to receive(:request) { double('Request', {:params => { | |
71 | "connection" => "google-oauth2", "redirect_uri" => "redirect_uri" }, :env => {}}) } | |
72 | expect(subject.authorize_params).to include("connection") | |
73 | expect(subject.authorize_params).to include("state") | |
74 | expect(subject.authorize_params).to include("redirect_uri") | |
75 | end | |
76 | end | |
77 | ||
78 | describe "callback phase" do | |
79 | before :each do | |
80 | @raw_info = { | |
81 | "_id" => "165dabb5140ee2cc66b5137912ccd760", | |
82 | "email" => "user@mail.com", | |
83 | "family_name" => "LastName", | |
84 | "gender" => "male", | |
85 | "given_name" => "FirstName", | |
86 | "identities" => [ | |
87 | { | |
88 | "access_token" => "ya29.AHES6ZRPK1Skc_rtB30Em_5RkZlKez3FkktcmJ_0RX5fIkCbkOCrXA", | |
89 | "provider" => "google-oauth2", | |
90 | "user_id" => "102835921788417079450", | |
91 | "connection" => "google-oauth2", | |
92 | "isSocial" => true | |
93 | } | |
94 | ], | |
95 | "locale" => "en", | |
96 | "name" => "FirstName LastName", | |
97 | "nickname" => "nick", | |
98 | "picture" => "pic", | |
99 | "user_id" => "google-oauth2|102835921788417079450" | |
100 | } | |
101 | allow(subject).to receive(:raw_info) { @raw_info } | |
102 | end | |
103 | ||
104 | context "info" do | |
105 | it 'returns the uid (required)' do | |
106 | expect(subject.uid).to eq('google-oauth2|102835921788417079450') | |
107 | end | |
108 | ||
109 | it 'returns the name (required)' do | |
110 | expect(subject.info[:name]).to eq('FirstName LastName') | |
111 | end | |
112 | ||
113 | it 'returns the email' do | |
114 | expect(subject.info[:email]).to eq('user@mail.com') | |
115 | end | |
116 | ||
117 | it 'returns the nickname' do | |
118 | expect(subject.info[:nickname]).to eq('nick') | |
119 | end | |
120 | ||
121 | it 'returns the last name' do | |
122 | expect(subject.info[:last_name]).to eq('LastName') | |
123 | end | |
124 | ||
125 | it 'returns the first name' do | |
126 | expect(subject.info[:first_name]).to eq('FirstName') | |
127 | end | |
128 | ||
129 | it 'returns the location' do | |
130 | expect(subject.info[:location]).to eq('en') | |
131 | end | |
132 | ||
133 | it 'returns the image' do | |
134 | expect(subject.info[:image]).to eq('pic') | |
135 | end | |
136 | end | |
137 | ||
138 | context "get token" do | |
139 | before :each do | |
140 | @access_token = double('OAuth2::AccessToken') | |
141 | ||
142 | allow(@access_token).to receive(:token) | |
143 | allow(@access_token).to receive(:expires?) | |
144 | allow(@access_token).to receive(:expires_at) | |
145 | allow(@access_token).to receive(:refresh_token) | |
146 | allow(@access_token).to receive(:params) | |
147 | ||
148 | allow(subject).to receive(:access_token) { @access_token } | |
149 | end | |
150 | ||
151 | it 'returns a Hash' do | |
152 | expect(subject.credentials).to be_a(Hash) | |
153 | end | |
154 | ||
155 | it 'returns the token' do | |
156 | allow(@access_token).to receive(:token) { | |
157 | { | |
158 | :access_token => "OTqSFa9zrh0VRGAZHH4QPJISCoynRwSy9FocUazuaU950EVcISsJo3pST11iTCiI", | |
159 | :token_type => "bearer" | |
160 | } } | |
161 | expect(subject.credentials['token'][:access_token]).to eq('OTqSFa9zrh0VRGAZHH4QPJISCoynRwSy9FocUazuaU950EVcISsJo3pST11iTCiI') | |
162 | expect(subject.credentials['token'][:token_type]).to eq('bearer') | |
163 | end | |
164 | ||
165 | it 'returns the refresh token' do | |
166 | allow(@access_token).to receive(:refresh_token) { "your_refresh_token" } | |
167 | allow(@access_token).to receive(:params) { | |
168 | { | |
169 | 'id_token' => "your_id_token", | |
170 | 'token_type' => "your_token_type" | |
171 | } } | |
172 | expect(subject.credentials['refresh_token']).to eq('your_refresh_token') | |
173 | end | |
174 | end | |
175 | end | |
176 | end | |
7 | let(:client_id) { 'CLIENT_ID' } | |
8 | let(:client_secret) { 'CLIENT_SECRET' } | |
9 | let(:domain_url) { 'https://samples.auth0.com' } | |
10 | let(:application) do | |
11 | lambda do | |
12 | [200, {}, ['Hello.']] | |
13 | end | |
14 | end | |
15 | let(:auth0) do | |
16 | OmniAuth::Strategies::Auth0.new( | |
17 | application, | |
18 | client_id, | |
19 | client_secret, | |
20 | domain_url | |
21 | ) | |
22 | end | |
23 | ||
24 | describe 'client_options' do | |
25 | let(:subject) { auth0.client } | |
26 | ||
27 | context 'domain with https' do | |
28 | let(:domain_url) { 'https://samples.auth0.com' } | |
29 | it_behaves_like 'site has valid domain url', 'https://samples.auth0.com' | |
30 | end | |
31 | ||
32 | context 'domain with http' do | |
33 | let(:domain_url) { 'http://mydomain.com' } | |
34 | it_behaves_like 'site has valid domain url', 'http://mydomain.com' | |
35 | end | |
36 | ||
37 | context 'domain with host only' do | |
38 | let(:domain_url) { 'samples.auth0.com' } | |
39 | it_behaves_like 'site has valid domain url', 'https://samples.auth0.com' | |
40 | end | |
41 | ||
42 | it 'should have correct authorize path' do | |
43 | expect(subject.options[:authorize_url]).to eq('/authorize') | |
44 | end | |
45 | ||
46 | it 'should have the correct userinfo path' do | |
47 | expect(subject.options[:userinfo_url]).to eq('/userinfo') | |
48 | end | |
49 | ||
50 | it 'should have the correct token path' do | |
51 | expect(subject.options[:token_url]).to eq('/oauth/token') | |
52 | end | |
53 | end | |
54 | ||
55 | describe 'options' do | |
56 | let(:subject) { auth0.options } | |
57 | ||
58 | it 'should have the correct client_id' do | |
59 | expect(subject[:client_id]).to eq(client_id) | |
60 | end | |
61 | ||
62 | it 'should have the correct client secret' do | |
63 | expect(subject[:client_secret]).to eq(client_secret) | |
64 | end | |
65 | it 'should have correct domain' do | |
66 | expect(subject[:domain]).to eq(domain_url) | |
67 | end | |
68 | end | |
69 | ||
70 | describe 'oauth' do | |
71 | it 'redirects to hosted login page' do | |
72 | get 'auth/auth0' | |
73 | expect(last_response.status).to eq(302) | |
74 | redirect_url = last_response.headers['Location'] | |
75 | expect(redirect_url).to start_with('https://samples.auth0.com/authorize') | |
76 | expect(redirect_url).to have_query('response_type', 'code') | |
77 | expect(redirect_url).to have_query('state') | |
78 | expect(redirect_url).to have_query('client_id') | |
79 | expect(redirect_url).to have_query('redirect_uri') | |
80 | end | |
81 | ||
82 | describe 'callback' do | |
83 | let(:access_token) { 'access token' } | |
84 | let(:expires_in) { 2000 } | |
85 | let(:token_type) { 'bearer' } | |
86 | let(:refresh_token) { 'refresh token' } | |
87 | let(:id_token) { 'id token' } | |
88 | ||
89 | let(:user_id) { 'user identifier' } | |
90 | let(:state) { SecureRandom.hex(8) } | |
91 | let(:name) { 'John' } | |
92 | let(:nickname) { 'J' } | |
93 | let(:picture) { 'some picture url' } | |
94 | let(:email) { 'mail@mail.com' } | |
95 | let(:email_verified) { true } | |
96 | ||
97 | let(:oauth_response) do | |
98 | { | |
99 | access_token: access_token, | |
100 | expires_in: expires_in, | |
101 | token_type: token_type | |
102 | } | |
103 | end | |
104 | ||
105 | let(:oidc_response) do | |
106 | { | |
107 | id_token: id_token, | |
108 | access_token: access_token, | |
109 | expires_in: expires_in, | |
110 | token_type: token_type | |
111 | } | |
112 | end | |
113 | ||
114 | let(:basic_user_info) { { sub: user_id } } | |
115 | let(:oidc_user_info) do | |
116 | { | |
117 | sub: user_id, | |
118 | name: name, | |
119 | nickname: nickname, | |
120 | email: email, | |
121 | picture: picture, | |
122 | email_verified: email_verified | |
123 | } | |
124 | end | |
125 | ||
126 | def stub_auth(body) | |
127 | stub_request(:post, 'https://samples.auth0.com/oauth/token') | |
128 | .to_return( | |
129 | headers: { 'Content-Type' => 'application/json' }, | |
130 | body: MultiJson.encode(body) | |
131 | ) | |
132 | end | |
133 | ||
134 | def stub_userinfo(body) | |
135 | stub_request(:get, 'https://samples.auth0.com/userinfo') | |
136 | .to_return( | |
137 | headers: { 'Content-Type' => 'application/json' }, | |
138 | body: MultiJson.encode(body) | |
139 | ) | |
140 | end | |
141 | ||
142 | def trigger_callback | |
143 | get '/auth/auth0/callback', { 'state' => state }, | |
144 | 'rack.session' => { 'omniauth.state' => state } | |
145 | end | |
146 | ||
147 | before(:each) do | |
148 | WebMock.reset! | |
149 | end | |
150 | ||
151 | let(:subject) { MultiJson.decode(last_response.body) } | |
152 | ||
153 | context 'basic oauth' do | |
154 | before do | |
155 | stub_auth(oauth_response) | |
156 | stub_userinfo(basic_user_info) | |
157 | trigger_callback | |
158 | end | |
159 | ||
160 | it 'to succeed' do | |
161 | expect(last_response.status).to eq(200) | |
162 | end | |
163 | ||
164 | it 'has credentials' do | |
165 | expect(subject['credentials']['token']).to eq(access_token) | |
166 | expect(subject['credentials']['expires']).to be true | |
167 | expect(subject['credentials']['expires_at']).to_not be_nil | |
168 | end | |
169 | ||
170 | it 'has basic values' do | |
171 | expect(subject['provider']).to eq('auth0') | |
172 | expect(subject['uid']).to eq(user_id) | |
173 | expect(subject['info']['name']).to eq(user_id) | |
174 | end | |
175 | end | |
176 | ||
177 | context 'basic oauth w/refresh token' do | |
178 | before do | |
179 | stub_auth(oauth_response.merge(refresh_token: refresh_token)) | |
180 | stub_userinfo(basic_user_info) | |
181 | trigger_callback | |
182 | end | |
183 | ||
184 | it 'to succeed' do | |
185 | expect(last_response.status).to eq(200) | |
186 | end | |
187 | ||
188 | it 'has credentials' do | |
189 | expect(subject['credentials']['token']).to eq(access_token) | |
190 | expect(subject['credentials']['refresh_token']).to eq(refresh_token) | |
191 | expect(subject['credentials']['expires']).to be true | |
192 | expect(subject['credentials']['expires_at']).to_not be_nil | |
193 | end | |
194 | end | |
195 | ||
196 | context 'oidc' do | |
197 | before do | |
198 | stub_auth(oidc_response) | |
199 | stub_userinfo(oidc_user_info) | |
200 | trigger_callback | |
201 | end | |
202 | ||
203 | it 'to succeed' do | |
204 | expect(last_response.status).to eq(200) | |
205 | end | |
206 | ||
207 | it 'has credentials' do | |
208 | expect(subject['credentials']['token']).to eq(access_token) | |
209 | expect(subject['credentials']['expires']).to be true | |
210 | expect(subject['credentials']['expires_at']).to_not be_nil | |
211 | expect(subject['credentials']['id_token']).to eq(id_token) | |
212 | end | |
213 | ||
214 | it 'has basic values' do | |
215 | expect(subject['provider']).to eq('auth0') | |
216 | expect(subject['uid']).to eq(user_id) | |
217 | end | |
218 | ||
219 | it 'has info' do | |
220 | expect(subject['info']['name']).to eq(name) | |
221 | expect(subject['info']['nickname']).to eq(nickname) | |
222 | expect(subject['info']['image']).to eq(picture) | |
223 | expect(subject['info']['email']).to eq(email) | |
224 | end | |
225 | ||
226 | it 'has extra' do | |
227 | expect(subject['extra']['raw_info']['email_verified']).to be true | |
228 | end | |
229 | end | |
230 | end | |
231 | end | |
232 | ||
233 | describe 'error_handling' do | |
234 | it 'fails when missing client_id' do | |
235 | @app = make_application(client_id: nil) | |
236 | get 'auth/auth0' | |
237 | expect(last_response.status).to eq(302) | |
238 | redirect_url = last_response.headers['Location'] | |
239 | expect(redirect_url).to fail_auth_with('missing_client_id') | |
240 | end | |
241 | ||
242 | it 'fails when missing client_secret' do | |
243 | @app = make_application(client_secret: nil) | |
244 | get 'auth/auth0' | |
245 | expect(last_response.status).to eq(302) | |
246 | redirect_url = last_response.headers['Location'] | |
247 | expect(redirect_url).to fail_auth_with('missing_client_secret') | |
248 | end | |
249 | ||
250 | it 'fails when missing domain' do | |
251 | @app = make_application(domain: nil) | |
252 | get 'auth/auth0' | |
253 | expect(last_response.status).to eq(302) | |
254 | redirect_url = last_response.headers['Location'] | |
255 | expect(redirect_url).to fail_auth_with('missing_domain') | |
256 | end | |
257 | end | |
258 | end | |
259 | ||
260 | RSpec::Matchers.define :fail_auth_with do |message| | |
261 | match do |actual| | |
262 | uri = URI(actual) | |
263 | query = CGI.parse(uri.query) | |
264 | (uri.path == '/auth/failure') && | |
265 | (query['message'] == [message]) && | |
266 | (query['strategy'] == ['auth0']) | |
267 | end | |
268 | end | |
269 | ||
270 | RSpec::Matchers.define :have_query do |key, value| | |
271 | match do |actual| | |
272 | uri = redirect_uri(actual) | |
273 | query = query(uri) | |
274 | if value.nil? | |
275 | query[key].length == 1 | |
276 | else | |
277 | query[key] == [value] | |
278 | end | |
279 | end | |
280 | ||
281 | def redirect_uri(string) | |
282 | URI(string) | |
283 | end | |
284 | ||
285 | def query(uri) | |
286 | CGI.parse(uri.query) | |
287 | end | |
288 | end |
0 | $:.unshift File.expand_path('..', __FILE__) | |
1 | $:.unshift File.expand_path('../../lib', __FILE__) | |
0 | $LOAD_PATH.unshift File.expand_path('..', __FILE__) | |
1 | $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) | |
2 | ||
2 | 3 | require 'simplecov' |
3 | SimpleCov.start | |
4 | if ENV['COVERAGE'] | |
5 | SimpleCov.start do | |
6 | minimum_coverage(89.8) | |
7 | end | |
8 | end | |
4 | 9 | require 'rspec' |
5 | 10 | require 'rack/test' |
6 | 11 | require 'webmock/rspec' |
7 | 12 | require 'omniauth' |
8 | 13 | require 'omniauth-auth0' |
14 | require 'sinatra' | |
15 | ||
16 | WebMock.disable_net_connect! | |
9 | 17 | |
10 | 18 | RSpec.configure do |config| |
11 | config.include WebMock::API | |
12 | config.include Rack::Test::Methods | |
13 | config.extend OmniAuth::Test::StrategyMacros, :type => :strategy | |
14 | config.color = true | |
15 | config.formatter = 'documentation' | |
16 | end⏎ | |
19 | config.include WebMock::API | |
20 | config.include Rack::Test::Methods | |
21 | config.extend OmniAuth::Test::StrategyMacros, type: :strategy | |
22 | ||
23 | def app | |
24 | @app || make_application | |
25 | end | |
26 | ||
27 | def make_application(options = {}) | |
28 | client_id = 'CLIENT_ID' | |
29 | secret = 'CLIENT_SECRET' | |
30 | domain = 'samples.auth0.com' | |
31 | client_id = options.delete(:client_id) if options.key?(:client_id) | |
32 | secret = options.delete(:client_secret) if options.key?(:client_secret) | |
33 | domain = options.delete(:domain) if options.key?(:domain) | |
34 | ||
35 | Sinatra.new do | |
36 | configure do | |
37 | enable :sessions | |
38 | set :show_exceptions, false | |
39 | set :session_secret, 'TEST' | |
40 | end | |
41 | ||
42 | use OmniAuth::Builder do | |
43 | provider :auth0, client_id, secret, domain, options | |
44 | end | |
45 | ||
46 | get '/auth/auth0/callback' do | |
47 | MultiJson.encode(env['omniauth.auth']) | |
48 | end | |
49 | end | |
50 | end | |
51 | end | |
52 | ||
53 | OmniAuth.config.logger = Logger.new('/dev/null') |