grape_token_auth 0.0.0 → 0.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/.ruby-version +1 -0
- data/CONTRIBUTING.md +46 -0
- data/README.md +222 -12
- data/Rakefile +11 -1
- data/bin/rspec +16 -0
- data/circle.yml +6 -0
- data/config/database.yml +8 -0
- data/grape_token_auth.gemspec +15 -0
- data/lib/grape_token_auth/api_helpers.rb +30 -0
- data/lib/grape_token_auth/apis/confirmation_api.rb +49 -0
- data/lib/grape_token_auth/apis/omniauth_api.rb +149 -0
- data/lib/grape_token_auth/apis/password_api.rb +138 -0
- data/lib/grape_token_auth/apis/registration_api.rb +88 -0
- data/lib/grape_token_auth/apis/session_api.rb +60 -0
- data/lib/grape_token_auth/apis/token_validation_api.rb +29 -0
- data/lib/grape_token_auth/authentication_header.rb +52 -0
- data/lib/grape_token_auth/authorizer_data.rb +58 -0
- data/lib/grape_token_auth/configuration.rb +81 -0
- data/lib/grape_token_auth/exceptions.rb +29 -0
- data/lib/grape_token_auth/key_generator.rb +44 -0
- data/lib/grape_token_auth/lookup_token.rb +46 -0
- data/lib/grape_token_auth/mail/mail.rb +28 -0
- data/lib/grape_token_auth/mail/message_base.rb +34 -0
- data/lib/grape_token_auth/mail/messages/confirmation/confirmation.html.erb +16 -0
- data/lib/grape_token_auth/mail/messages/confirmation/confirmation.text.erb +8 -0
- data/lib/grape_token_auth/mail/messages/confirmation/confirmation_email.rb +27 -0
- data/lib/grape_token_auth/mail/messages/password_reset/password_reset.html.erb +18 -0
- data/lib/grape_token_auth/mail/messages/password_reset/password_reset.text.erb +9 -0
- data/lib/grape_token_auth/mail/messages/password_reset/password_reset_email.rb +27 -0
- data/lib/grape_token_auth/mail/smtp_mailer.rb +50 -0
- data/lib/grape_token_auth/middleware.rb +42 -0
- data/lib/grape_token_auth/mount_helpers.rb +80 -0
- data/lib/grape_token_auth/omniauth/omniauth_failure_html.rb +26 -0
- data/lib/grape_token_auth/omniauth/omniauth_html_base.rb +23 -0
- data/lib/grape_token_auth/omniauth/omniauth_resource.rb +109 -0
- data/lib/grape_token_auth/omniauth/omniauth_success_html.rb +61 -0
- data/lib/grape_token_auth/omniauth/response_template.html.erb +38 -0
- data/lib/grape_token_auth/orm_integrations/active_record_token_auth.rb +310 -0
- data/lib/grape_token_auth/resource/resource_creator.rb +48 -0
- data/lib/grape_token_auth/resource/resource_crud_base.rb +43 -0
- data/lib/grape_token_auth/resource/resource_finder.rb +53 -0
- data/lib/grape_token_auth/resource/resource_updater.rb +40 -0
- data/lib/grape_token_auth/token.rb +23 -0
- data/lib/grape_token_auth/token_authentication.rb +8 -0
- data/lib/grape_token_auth/token_authorizer.rb +60 -0
- data/lib/grape_token_auth/unauthorized_middleware.rb +20 -0
- data/lib/grape_token_auth/version.rb +1 -1
- data/lib/grape_token_auth.rb +65 -2
- metadata +266 -13
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<h1>Email Confirmation</h1>
|
8
|
+
<p>Hello,</p>
|
9
|
+
|
10
|
+
<p>To activate your account please confirm your email by clicking the link below:</p>
|
11
|
+
|
12
|
+
<a href="<%= confirmation_link %>"><%= confirmation_link %></a>
|
13
|
+
|
14
|
+
<p>If you did not submit this request, please ignore this email</p>
|
15
|
+
</body>
|
16
|
+
</html>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
module Mail
|
3
|
+
class ConfirmationEmail < MessageBase
|
4
|
+
TEXT_TEMPLATE = File.expand_path('../confirmation.text.erb', __FILE__)
|
5
|
+
HTML_TEMPLATE = File.expand_path('../confirmation.html.erb', __FILE__)
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@subject = opts[:subject] || 'Confirm your email'
|
9
|
+
super(opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
def confirmation_link
|
13
|
+
protocol = url_options[:ssl] ? URI::HTTPS : URI::HTTP
|
14
|
+
options = url_options.merge(query: confirmation_params.to_query)
|
15
|
+
protocol.build(options).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def confirmation_params
|
19
|
+
{
|
20
|
+
redirect_url: opts[:redirect_url],
|
21
|
+
config: opts[:client_config],
|
22
|
+
confirmation_token: opts[:token]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
|
5
|
+
</head>
|
6
|
+
<body>
|
7
|
+
<h1>Password Reset</h1>
|
8
|
+
<p>Hello,</p>
|
9
|
+
|
10
|
+
<p> A password request has been submitted for your account, in order to
|
11
|
+
reset your password, please click the link below or copy it into your
|
12
|
+
browser:</p>
|
13
|
+
|
14
|
+
<a href="<%= reset_link %>"><%= reset_link %></a>
|
15
|
+
|
16
|
+
<p>If you did not submit this request, please ignore this email</p>
|
17
|
+
</body>
|
18
|
+
</html>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
module Mail
|
3
|
+
class PasswordResetEmail < MessageBase
|
4
|
+
TEXT_TEMPLATE = File.expand_path('../password_reset.text.erb', __FILE__)
|
5
|
+
HTML_TEMPLATE = File.expand_path('../password_reset.html.erb', __FILE__)
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@subject = opts[:subject] || 'Password Reset'
|
9
|
+
super(opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset_link
|
13
|
+
protocol = url_options[:ssl] ? URI::HTTPS : URI::HTTP
|
14
|
+
options = url_options.merge(query: reset_params.to_query, path: opts[:edit_path])
|
15
|
+
protocol.build(options).to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
def reset_params
|
19
|
+
{
|
20
|
+
redirect_url: opts[:redirect_url],
|
21
|
+
config: opts[:client_config],
|
22
|
+
reset_password_token: opts[:token]
|
23
|
+
}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
module Mail
|
3
|
+
class SMTPMailer
|
4
|
+
def initialize(message, opts)
|
5
|
+
@message = message
|
6
|
+
@opts = opts
|
7
|
+
@to_address = opts[:to] || opts['to']
|
8
|
+
end
|
9
|
+
|
10
|
+
def send_mail
|
11
|
+
email.deliver
|
12
|
+
end
|
13
|
+
|
14
|
+
def prepare_email!
|
15
|
+
@email = ::Mail.new
|
16
|
+
@email.to = to_address
|
17
|
+
@email.subject = message.subject
|
18
|
+
@email.from = GrapeTokenAuth.configuration.from_address
|
19
|
+
@email.text_part = prepare_text
|
20
|
+
@email.html_part = prepare_html
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.send!(message, options)
|
25
|
+
new(message, options).prepare_email!.send_mail
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_options?
|
29
|
+
return false unless to_address
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def prepare_html
|
36
|
+
part = ::Mail::Part.new
|
37
|
+
part.body = message.html_body
|
38
|
+
part
|
39
|
+
end
|
40
|
+
|
41
|
+
def prepare_text
|
42
|
+
part = ::Mail::Part.new
|
43
|
+
part.body = message.text_body
|
44
|
+
part
|
45
|
+
end
|
46
|
+
|
47
|
+
attr_reader :message, :email, :opts, :to_address
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
class Middleware
|
3
|
+
def initialize(app, _options)
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def call(env)
|
8
|
+
setup(env)
|
9
|
+
begin
|
10
|
+
responses_with_auth_headers(*@app.call(env))
|
11
|
+
rescue Unauthorized
|
12
|
+
return unauthorized
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :app, :request_start, :authorizer_data, :scope
|
19
|
+
|
20
|
+
def unauthorized
|
21
|
+
[401,
|
22
|
+
{ 'Content-Type' => 'application/json'
|
23
|
+
},
|
24
|
+
[]
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup(env)
|
29
|
+
@request_start = Time.now
|
30
|
+
@authorizer_data = AuthorizerData.from_env(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
def responses_with_auth_headers(status, headers, response)
|
34
|
+
auth_headers = AuthenticationHeader.new(authorizer_data, request_start)
|
35
|
+
[
|
36
|
+
status,
|
37
|
+
headers.merge(auth_headers.headers),
|
38
|
+
response
|
39
|
+
]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
module MountHelpers
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def mount_registration(opts = {})
|
9
|
+
mount_api('RegistrationAPI', opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
def mount_sessions(opts = {})
|
13
|
+
mount_api('SessionsAPI', opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def mount_confirmation(opts = {})
|
17
|
+
opts[:to] = opts[:to].to_s.chomp('/') + '/confirmation'
|
18
|
+
mount_api('ConfirmationAPI', opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
def mount_token_validation(opts = {})
|
22
|
+
mount_api('TokenValidationAPI', opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mount_password_reset(opts = {})
|
26
|
+
opts[:to] = opts[:to].to_s.chomp('/') + '/password'
|
27
|
+
mount_api('PasswordAPI', opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
def mount_omniauth(opts = {})
|
31
|
+
path = opts[:to] || '/'
|
32
|
+
|
33
|
+
if mapping = opts[:for]
|
34
|
+
api = create_api_subclass('OmniAuthAPI', mapping)
|
35
|
+
else
|
36
|
+
api = GrapeTokenAuth::OmniAuthAPI
|
37
|
+
end
|
38
|
+
|
39
|
+
mount api => path
|
40
|
+
end
|
41
|
+
|
42
|
+
def mount_omniauth_callbacks(opts = {})
|
43
|
+
fail 'Oauth callback API is not scope specific. Only mount it once and do not pass a "for" option' if opts[:for]
|
44
|
+
fail 'Oauth callback API path is specificed in the configuration. Do not pass a "to" option' if opts[:to]
|
45
|
+
prefix = GrapeTokenAuth.set_omniauth_path_prefix!
|
46
|
+
mount GrapeTokenAuth::OmniAuthCallBackRouterAPI => prefix
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def mount_api(api_class_name, opts)
|
52
|
+
path = opts[:to] || '/'
|
53
|
+
|
54
|
+
if opts[:for]
|
55
|
+
api = create_api_subclass(api_class_name, opts[:for])
|
56
|
+
else
|
57
|
+
api = GrapeTokenAuth.const_get(api_class_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
mount api => path
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_api_subclass(class_name, mapping)
|
64
|
+
resource_class = GrapeTokenAuth.configuration.scope_to_class(mapping)
|
65
|
+
fail ScopeUndefinedError.new(nil, mapping) unless resource_class
|
66
|
+
scope_name = mapping.to_s.split('_').collect(&:capitalize).join
|
67
|
+
klass = Class.new(Grape::API) do
|
68
|
+
class << self
|
69
|
+
def resource_scope
|
70
|
+
@resource_scope
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
klass.instance_variable_set(:@resource_scope, mapping)
|
75
|
+
klass.include(GrapeTokenAuth.const_get("#{class_name}Core"))
|
76
|
+
GrapeTokenAuth.const_set("#{scope_name}#{class_name}", klass)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative './omniauth_html_base.rb'
|
2
|
+
|
3
|
+
module GrapeTokenAuth
|
4
|
+
class OmniAuthFailureHTML < OmniAuthHTMLBase
|
5
|
+
FAILURE_MESSAGE = 'authFailure'
|
6
|
+
|
7
|
+
def initialize(error_message)
|
8
|
+
@error_message = error_message
|
9
|
+
end
|
10
|
+
|
11
|
+
def auth_origin_url
|
12
|
+
"/#?error=#{error_message}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def json_post_data
|
16
|
+
{
|
17
|
+
'message' => FAILURE_MESSAGE,
|
18
|
+
'error' => error_message
|
19
|
+
}.to_json
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :error_message
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module GrapeTokenAuth
|
5
|
+
class OmniAuthHTMLBase
|
6
|
+
def render_html
|
7
|
+
unless respond_to?(:json_post_data) && respond_to?(:auth_origin_url)
|
8
|
+
fail 'Invalid OmniAuthHTMLBase class'
|
9
|
+
end
|
10
|
+
template.result(binding)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def template_path
|
16
|
+
File.expand_path('../response_template.html.erb', __FILE__)
|
17
|
+
end
|
18
|
+
|
19
|
+
def template
|
20
|
+
ERB.new(File.read(template_path))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module GrapeTokenAuth
|
2
|
+
class OmniAuthResource
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
attr_reader :resource
|
6
|
+
|
7
|
+
def_delegators :token, :expiry, :client_id
|
8
|
+
def_delegator :resource, :uid
|
9
|
+
|
10
|
+
def initialize(resource, auth_hash, omniauth_params)
|
11
|
+
@resource = resource
|
12
|
+
@auth_hash = auth_hash
|
13
|
+
@omniauth_params = omniauth_params
|
14
|
+
end
|
15
|
+
|
16
|
+
def persist_oauth_attributes!
|
17
|
+
set_crazy_password
|
18
|
+
sync_token_to_resource
|
19
|
+
sync_attributes_to_resource
|
20
|
+
# skip_confirmable_email
|
21
|
+
resource.save!
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.fetch_or_create(resource_class, auth_hash, oauth_params)
|
25
|
+
resource = resource_class.where(
|
26
|
+
uid: auth_hash['uid'],
|
27
|
+
provider: auth_hash['provider']).first_or_initialize
|
28
|
+
new(resource, auth_hash, oauth_params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def token
|
32
|
+
@token ||= Token.new
|
33
|
+
end
|
34
|
+
|
35
|
+
def token_value
|
36
|
+
token.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def attributes
|
40
|
+
{ 'auth_token' => token_value,
|
41
|
+
'client_id' => token.client_id,
|
42
|
+
'expiry' => token.expiry }.merge(resource.serializable_hash)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_reader :auth_hash, :omniauth_params
|
48
|
+
|
49
|
+
def set_crazy_password
|
50
|
+
# set crazy password for new oauth users. this is only used to prevent
|
51
|
+
# access via email sign-in.
|
52
|
+
return if resource.id
|
53
|
+
p = SecureRandom.urlsafe_base64(nil, false)
|
54
|
+
resource.password = p
|
55
|
+
resource.password_confirmation = p
|
56
|
+
end
|
57
|
+
|
58
|
+
def sync_attributes_to_resource
|
59
|
+
# sync user info with provider, update/generate auth token
|
60
|
+
assign_provider_attrs
|
61
|
+
|
62
|
+
# assign any additional (whitelisted) attributes
|
63
|
+
assign_extra_attributes
|
64
|
+
end
|
65
|
+
|
66
|
+
def assign_provider_attrs
|
67
|
+
info_hash = auth_hash['info']
|
68
|
+
attrs = %i(nickname name image email).each_with_object({}) do |k, hsh|
|
69
|
+
hsh[k] = info_hash.fetch(k, '')
|
70
|
+
end
|
71
|
+
resource.assign_attributes(attrs)
|
72
|
+
end
|
73
|
+
|
74
|
+
def assign_extra_attributes
|
75
|
+
extra_params = whitelisted_params
|
76
|
+
resource.assign_attributes(extra_params) if extra_params
|
77
|
+
end
|
78
|
+
|
79
|
+
def whitelisted_params
|
80
|
+
whitelist = GrapeTokenAuth.configuration.param_white_list
|
81
|
+
return unless whitelist
|
82
|
+
scoped_list = whitelist[scope] || whitelist[scope.to_s]
|
83
|
+
return unless scoped_list
|
84
|
+
scoped_list.each_with_object({}) do |key, permitted|
|
85
|
+
value = find_with_indifference(omniauth_params, key)
|
86
|
+
permitted[key] = value if value
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def scope
|
91
|
+
klass = resource.class
|
92
|
+
@scope ||= GrapeTokenAuth.configuration.mappings
|
93
|
+
.find { |k,v| v == klass }.try(:[], 0)
|
94
|
+
end
|
95
|
+
|
96
|
+
def find_with_indifference(hash, key)
|
97
|
+
if hash.key?(key.to_sym)
|
98
|
+
return hash[key.to_sym]
|
99
|
+
elsif hash.key?(key.to_s)
|
100
|
+
return hash[key.to_s]
|
101
|
+
end
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def sync_token_to_resource
|
106
|
+
resource.tokens[token.client_id] = token.to_h
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative './omniauth_html_base.rb'
|
2
|
+
|
3
|
+
module GrapeTokenAuth
|
4
|
+
class OmniAuthSuccessHTML < OmniAuthHTMLBase
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
SUCCESS_MESSAGE = 'deliverCredentials'
|
8
|
+
|
9
|
+
def_delegators :oauth_resource, :resource, :persist_oauth_attributes!
|
10
|
+
|
11
|
+
def initialize(oauth_resource, auth_hash, omniauth_params)
|
12
|
+
@oauth_resource = oauth_resource
|
13
|
+
@auth_hash = auth_hash
|
14
|
+
@omniauth_params = omniauth_params
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.build(resource_class, auth_hash, omniauth_params)
|
18
|
+
oauth_resource = OmniAuthResource.fetch_or_create(resource_class,
|
19
|
+
auth_hash,
|
20
|
+
omniauth_params)
|
21
|
+
new(oauth_resource, auth_hash, omniauth_params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def auth_origin_url
|
25
|
+
@omniauth_params['auth_origin_url'] || @omniauth_params[:auth_origin_url]
|
26
|
+
end
|
27
|
+
|
28
|
+
def window_type
|
29
|
+
@omniauth_params['omniauth_window_type'] ||
|
30
|
+
@omniauth_params[:omniauth_window_type]
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_redirect_url
|
34
|
+
"#{auth_origin_url}?#{auth_origin_query_params.to_query}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def json_post_data
|
38
|
+
success_attributes = { 'message' => SUCCESS_MESSAGE,
|
39
|
+
'config' => omniauth_params['config'] }
|
40
|
+
oauth_resource.attributes.merge(success_attributes).to_json
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :oauth_resource, :omniauth_params
|
46
|
+
|
47
|
+
def config
|
48
|
+
omniauth_params['config_name']
|
49
|
+
end
|
50
|
+
|
51
|
+
def auth_origin_query_params
|
52
|
+
{
|
53
|
+
auth_token: oauth_resource.token,
|
54
|
+
client_id: oauth_resource.client_id,
|
55
|
+
uid: oauth_resource.uid,
|
56
|
+
expiry: oauth_resource.expiry,
|
57
|
+
config: config
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<script>
|
5
|
+
/*
|
6
|
+
The data is accessible in two ways:
|
7
|
+
|
8
|
+
1. Using the postMessage api, this window will respond to a
|
9
|
+
'message' event with a post of all the data. (This can
|
10
|
+
be used by browsers other than IE if this window was
|
11
|
+
opened with window.open())
|
12
|
+
2. This window has a function called requestCredentials which,
|
13
|
+
when called, will return the data. (This can be
|
14
|
+
used if this window was opened in an inAppBrowser using
|
15
|
+
Cordova / PhoneGap)
|
16
|
+
*/
|
17
|
+
|
18
|
+
var data = <%= json_post_data %>;
|
19
|
+
|
20
|
+
window.addEventListener("message", function(ev) {
|
21
|
+
if (ev.data === "requestCredentials") {
|
22
|
+
ev.source.postMessage(data, '*');
|
23
|
+
window.close();
|
24
|
+
}
|
25
|
+
});
|
26
|
+
function requestCredentials() {
|
27
|
+
return data;
|
28
|
+
}
|
29
|
+
setTimeout(function() {
|
30
|
+
document.getElementById('text').innerHTML = (data && data.error) || 'Redirecting...';
|
31
|
+
}, 1000);
|
32
|
+
</script>
|
33
|
+
</head>
|
34
|
+
<body>
|
35
|
+
<pre id="text">
|
36
|
+
</pre>
|
37
|
+
</body>
|
38
|
+
</html>
|