motion-authentication 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 88c921f20aa4544926a47cae648753a20dbbab4a
4
- data.tar.gz: bb8c436ffc5f4116084f3540a7f5f7c53a5d2cbb
2
+ SHA256:
3
+ metadata.gz: ab7ad1c6522f447bb8e957077b29e783d5ec6175d67f9f08809f2089ea4c6383
4
+ data.tar.gz: aefda12e3ef3a7f8799d1d5390004a164e5379a83316fb17dcceeff3ca5d3606
5
5
  SHA512:
6
- metadata.gz: f79627619ffade80b261dcb7038e85c96d98556baeef095402e0cccd79ddee84b35ee34c1ade5202ebc50389f8d00bcdf0ce5e39df9d8e2217d1c96d8b93aa81
7
- data.tar.gz: 4c56cc20639741eac36e5868f4310a52fdbf68067c29a8edd4c540eb97a5a17fe68d9d404b1afd907d4fea2c8ea7eb4bb82a6a0636891f2c9f86f422d37a5db3
6
+ metadata.gz: ef8b4a0d2abf1ecf42ab67df9244bbbb82b5e464fcc782e7fa6fd4655ffe88b4eb2babced62efbd5178ea9791c6e83417d61397cb03199258ac698566fb74bac
7
+ data.tar.gz: 9a025671043d81dfb2a857edf810caf1964824cbb784f9ed5f32d53e10abcdf246251d9db2ae351f958921ae957a84e0d62249ac47cbc38df0c991374b3d1450
data/README.md CHANGED
@@ -4,6 +4,8 @@
4
4
 
5
5
  Currently, this library only supports iOS, but could easily support other platforms. Please submit an issue (or PR :D) for the platform you would like to support.
6
6
 
7
+ Need authorization? Use [`motion-authorization`](https://github.com/rubymotion-community/motion-authorization)!
8
+
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's `Gemfile`, then run `bundle install`:
@@ -19,13 +21,23 @@ Start by subclassing `Motion::Authentication` to create your own `Auth` class. S
19
21
  ```ruby
20
22
  class Auth < Motion::Authentication
21
23
  strategy DeviseTokenAuth
22
- sign_in_url "http://localhost:3000/api/v1/users/sign_in"
24
+ sign_in_url "https://example.com/api/v1/users/sign_in"
23
25
  end
24
26
  ```
25
27
 
26
28
  Available strategies:
27
29
 
28
- * `DeviseTokenAuth` - This authentication strategy takes `email` and `password`, makes a POST request to the `sign_in_url`, and expects the response to include `email` and `token` keys in the JSON response object.
30
+ * `DeviseCookieAuth` - This strategy supports the default way of authenticating with Devise, just as if you were submitting the sign in form using a web browser. It works by making an initial request to fetch the authenticity token, then submits the `email` and `password`, then stores the resulting cookie for authenticating future requests. If your user model has a different name (i.e. `AdminUser`), pass along the `namespace` option (i.e. `namespace: 'admin_user'`) when calling `sign_in`. Otherwise, namespace defaults to `:user`.
31
+
32
+ * `DeviseTokenAuth` - This authentication strategy is based on [José Valim's example gist](https://gist.github.com/josevalim/fb706b1e933ef01e4fb6) and is also in the format that Ember Simple Auth Devise adapter expects ([tutorial](http://romulomachado.github.io/2015/09/28/using-ember-simple-auth-with-devise.html))
33
+
34
+ This strategy takes `email` and `password`, makes a POST request to the `sign_in_url`, and expects the response to include `email` and `token` keys in the JSON response object.
35
+
36
+ * `DeviseTokenAuthGem` - This authentication strategy is compatible with the current version of the devise_auth_token gem at https://github.com/lynndylanhurley/devise_token_auth
37
+
38
+ Signing up: this strategy takes `email`, `password` and `password_confirmation`, makes a POST request to the `sign_up_url`, and expects the response to include `uid`, `access-token` and `client` keys in the response object headers.
39
+
40
+ Signing in: this strategy takes `email` and `password`, makes a POST request to the `sign_in_url`, and expects the response to include `uid`, `access-token` and `client` keys in the response object headers.
29
41
 
30
42
  ### `.sign_in`
31
43
 
@@ -36,13 +48,11 @@ Auth.sign_in(email: email, password: password) do |result|
36
48
  if result.success?
37
49
  # authentication successful!
38
50
  else
39
- app.alert "Invalid login?"
51
+ app.alert "Invalid email or password"
40
52
  end
41
53
  end
42
54
  ```
43
55
 
44
- A successful sign in will securely store the current user's auth token.
45
-
46
56
  ### `.signed_in?`
47
57
 
48
58
  You can check if an auth token has previously been stored by using `signed_in?`. For example, in your App Delegate, you might want to open your sign in screen when the app is opened:
@@ -59,7 +69,7 @@ end
59
69
 
60
70
  ### `.authorization_header`
61
71
 
62
- After signing in, and receiving the auth token, you will probably want to configure your API client to use your auth token in your API requests in an authorization header. Call `.authorization_header` to return the header value specific to the strategy that you are using. Two common places would be upon sign in, and when your app is launched.
72
+ After signing in, assuming you are using one of the token auth strategies, you will want to configure your API client to use your auth token in your API requests in an authorization header. Call `.authorization_header` to return the header value specific to the strategy that you are using. Two common places would be upon sign in, and when your app is launched.
63
73
 
64
74
  ```ruby
65
75
  # app_delegate.rb
@@ -81,6 +91,31 @@ def on_load(options)
81
91
  end
82
92
  ```
83
93
 
94
+ #### Note on `DeviseTokenAuthGem` strategy
95
+
96
+ The `devise_token_auth` gem requires all authenticated API calls to include the keys `uid`, `access-token` and `client` in the HTTP headers. Calling `.authorization_header` will return a hash with the proper key/value pairs. To include these as headers in all calls we recommend setting up your API client as follows:
97
+
98
+ ```ruby
99
+ ApiClient.update_authorization_header(Auth.authorization_header)
100
+
101
+ class ApiClient
102
+ class << self
103
+ def client
104
+ @client ||= AFMotion::SessionClient.build("http://localhost:3000/") do
105
+ response_serializer :json
106
+ header "Content-Type", "application/json"
107
+ end
108
+ end
109
+
110
+ def update_authorization_header(auth_headers_hash)
111
+ auth_headers_hash.each do |key, value|
112
+ client.headers[key] = value
113
+ end
114
+ end
115
+ end
116
+ end
117
+ ```
118
+
84
119
  ### `.sign_out`
85
120
 
86
121
  At some point, you're going to need to sign out. This method will clear the stored auth token, but also allows you to pass a block to be called after the token has been cleared.
@@ -4,8 +4,8 @@ unless defined?(Motion::Project::Config)
4
4
  raise "This file must be required within a RubyMotion project Rakefile."
5
5
  end
6
6
 
7
- require 'motion-cocoapods'
8
- require 'motion-keychain'
7
+ require 'motion-cocoapods' # TODO: this won't work for Android
8
+ require 'motion-keychain' # TODO: this won't work for Android
9
9
 
10
10
  lib_dir_path = File.dirname(File.expand_path(__FILE__))
11
11
  Motion::Project::App.setup do |app|
@@ -13,10 +13,23 @@ class Motion
13
13
  @sign_in_url
14
14
  end
15
15
 
16
+ def sign_up_url(val = nil)
17
+ @sign_up_url = val unless val.nil?
18
+ @sign_up_url
19
+ end
20
+
16
21
  def sign_in(params, &block)
17
22
  strategy.sign_in(sign_in_url, params, &block)
18
23
  end
19
24
 
25
+ def sign_up(params, &block)
26
+ strategy.sign_up(sign_up_url, params, &block)
27
+ end
28
+
29
+ def set_current_user
30
+ strategy.set_current_user
31
+ end
32
+
20
33
  def authorization_header
21
34
  strategy.authorization_header
22
35
  end
@@ -0,0 +1,57 @@
1
+ module Motion
2
+ class Authentication
3
+ class DeviseCookieAuth
4
+ class << self
5
+ def sign_in(sign_in_url, params, &block)
6
+ get_csrf_token(sign_in_url) do |param_name, token|
7
+ namespace = params[:namespace] || :user
8
+ HTTP.post(sign_in_url, form: { namespace => params, param_name => token }, follow_redirects: false) do |response|
9
+ if response.status_code == 302 # assume success due to redirect
10
+ cookie = NSHTTPCookieStorage.sharedHTTPCookieStorage.cookiesForURL(NSURL.URLWithString(sign_in_url)).first
11
+ store_session_cookie(cookie)
12
+ block.call(true)
13
+ else # didn't redirect, must be invalid credentials
14
+ block.call(false)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def get_csrf_token(sign_in_url, &block)
21
+ HTTP.get(sign_in_url) do |response|
22
+ doc = Motion::HTML.parse(response.body)
23
+ param_meta_tag = doc.query('head meta[name="csrf-param"]').first
24
+ token_meta_tag = doc.query('head meta[name="csrf-token"]').first
25
+ if param_meta_tag && token_meta_tag
26
+ param_name = param_meta_tag['content']
27
+ token = token_meta_tag['content']
28
+ block.call(param_name, token)
29
+ else
30
+ mp 'Couldnt parse CSRF token from HTML'
31
+ end
32
+ end
33
+ end
34
+
35
+ def store_session_cookie(cookie)
36
+ MotionKeychain.set :session_cookie, JSON.generate(properties: cookie.properties)
37
+ end
38
+
39
+ def signed_in?
40
+ MotionKeychain.get(:session_cookie) && restore_session
41
+ end
42
+
43
+ def restore_session
44
+ json = MotionKeychain.get(:session_cookie)
45
+ data = JSON.parse(json)
46
+ cookie = NSHTTPCookie.cookieWithProperties(data['properties'])
47
+ NSHTTPCookieStorage.sharedHTTPCookieStorage.setCookie(cookie)
48
+ end
49
+
50
+ def sign_out(&block)
51
+ MotionKeychain.remove :session_cookie
52
+ block.call
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -11,6 +11,15 @@ module Motion
11
11
  end
12
12
  end
13
13
 
14
+ def sign_up(sign_up_url, params, &block)
15
+ AFMotion::JSON.post(sign_up_url, user: params) do |response|
16
+ if response.success?
17
+ store_auth_tokens(response.object)
18
+ end
19
+ block.call(response)
20
+ end
21
+ end
22
+
14
23
  def store_auth_tokens(data)
15
24
  MotionKeychain.set :auth_email, data["email"]
16
25
  MotionKeychain.set :auth_token, data["token"]
@@ -0,0 +1,80 @@
1
+ module Motion
2
+ class Authentication
3
+ class DeviseTokenAuthGem
4
+ class << self
5
+
6
+ def sign_in(sign_in_url, params, &block)
7
+ AFMotion::JSON.post(sign_in_url, params) do |response|
8
+ if response.success?
9
+ store_auth_tokens(response.object,response.operation.response.allHeaderFields)
10
+ end
11
+ block.call(response)
12
+ end
13
+ end
14
+
15
+ def sign_up(sign_up_url, params, &block)
16
+ AFMotion::JSON.post(sign_up_url, params) do |response|
17
+ if response.success?
18
+ store_auth_tokens(response.object,response.operation.response.allHeaderFields)
19
+ end
20
+ block.call(response)
21
+ end
22
+ end
23
+
24
+ def store_auth_tokens(response,headers)
25
+ MotionKeychain.set :auth_uid, headers["uid"]
26
+ MotionKeychain.set :auth_token, headers["access-token"]
27
+ MotionKeychain.set :auth_client, headers["client"]
28
+ serialized_response = ""
29
+ response["data"].each do |key,value|
30
+ case key
31
+ when "assets"
32
+ value.each do |eachasset|
33
+ serialized_response << eachasset["name"] + "·" + eachasset["qty"].to_s + ","
34
+ end
35
+ when "friends"
36
+ #do nothing
37
+ else
38
+ serialized_response << key + "·" + value.to_s + ","
39
+ end
40
+ end
41
+ MotionKeychain.set :current_user, serialized_response
42
+ end
43
+
44
+ def set_current_user
45
+ deserialize(MotionKeychain.get :current_user)
46
+ end
47
+
48
+ def authorization_header
49
+ token = MotionKeychain.get :auth_token
50
+ uid = MotionKeychain.get :auth_uid
51
+ client = MotionKeychain.get :auth_client
52
+ {"access-token" => token, "uid" => uid, "client" => client }
53
+ end
54
+
55
+ def signed_in?
56
+ !! MotionKeychain.get(:auth_token)
57
+ end
58
+
59
+ def sign_out(&block)
60
+ MotionKeychain.remove :auth_uid
61
+ MotionKeychain.remove :auth_token
62
+ MotionKeychain.remove :auth_client
63
+ MotionKeychain.remove :current_user
64
+ block.call
65
+ end
66
+
67
+ def deserialize(mystring,arr_sep=',', key_sep='·')
68
+ array = mystring.split(arr_sep)
69
+ hash = {}
70
+ array.each do |e|
71
+ key_value = e.split(key_sep)
72
+ hash[key_value[0]] = key_value[1]
73
+ end
74
+ return hash
75
+ end
76
+
77
+ end
78
+ end
79
+ end
80
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-authentication
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Havens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-05 00:00:00.000000000 Z
11
+ date: 2019-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: motion-cocoapods
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: motion-http
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: motion-html
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: rake
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -63,8 +91,10 @@ files:
63
91
  - README.md
64
92
  - lib/motion-authentication.rb
65
93
  - lib/project/motion-authentication.rb
94
+ - lib/project/strategies/devise_cookie_auth.rb
66
95
  - lib/project/strategies/devise_token_auth.rb
67
- homepage: https://github.com/andrewhavens/motion-authentication
96
+ - lib/project/strategies/devise_token_auth_gem.rb
97
+ homepage: https://github.com/rubymotion-community/motion-authentication
68
98
  licenses:
69
99
  - MIT
70
100
  metadata: {}
@@ -83,8 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
113
  - !ruby/object:Gem::Version
84
114
  version: '0'
85
115
  requirements: []
86
- rubyforge_project:
87
- rubygems_version: 2.5.1
116
+ rubygems_version: 3.0.6
88
117
  signing_key:
89
118
  specification_version: 4
90
119
  summary: A simple, standardized authentication helper for common authentication strategies