ruby on rails - simple - Hacer que ng-token-auth trabaje con devise_token_auth
rails api devise authentication_token (7)
¿Has intentado agregar configuración para $ authProvider? Este ejemplo está en el archivo Léame de https://github.com/lynndylanhurley/devise_token_auth .
angular.module(''myApp'', [''ng-token-auth''])
.config(function($authProvider) {
$authProvider.configure({
apiUrl: ''http://api.example.com''
authProviderPaths: {
github: ''/auth/github'' // <-- note that this is different than what was set with github
}
});
});
Tengo un proyecto Rails and Ionic. El back-end usa la gema devise_token_auth, y la parte frontal ng-token-auth; se supone que estos deben funcionar "a la perfección".
Tengo todo funcionando en lo que respecta al registro e inicio de sesión, que devuelve un objeto de respuesta válido. Sin embargo, cualquier solicitud posterior después de usar $ state.go (''app.somepage'') dará como resultado 401 respuestas no autorizadas.
Tengo la sensación de que en realidad no estoy almacenando el token en ningún lado. ¿Puede ayudarme alguien, por favor?
Aquí hay algunos fragmentos:
.controller(''LoginCtrl'',[''$scope'', ''$auth'', ''$state'', function($scope, $auth, $state) {
$scope.loginForm = {}
$scope.handleLoginBtnClick = function() {
console.log($scope.loginForm);
$auth.submitLogin($scope.loginForm)
.then(function(resp) {
$state.go(''app.feed'');
})
.catch(function(resp) {
console.log(resp.errors);
});
};
Definición del estado:
.state(''app'', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: ''AppCtrl'',
resolve: {
auth: function($auth) {
return $auth.validateUser();
}
}
})
Recursos:
factory(''Post'', [''railsResourceFactory'', ''apiUrl'', function (railsResourceFactory, apiUrl) {
return railsResourceFactory({
url: apiUrl + ''/posts'',
name: ''post''
});
}]).
Y en PostsCtrl:
$scope.loadFeed = function() {
Post.query().then(function (posts) {
$scope.posts = posts;
}, function (error) {
console.log( ''Did not get posts!''); ### THIS FIRES
}).finally(function() {
// Stop the ion-refresher from spinning
$scope.$broadcast(''scroll.refreshComplete'');
});
};
Objeto de respuesta de inicio de sesión:
{"data":{"id":1,"provider":"email","uid":"1234","phone":null,"name":"Admin","image":null,"username":"admin"}}
Parte superior de ApplicationController:
class ApplicationController < ActionController::Base
include DeviseTokenAuth::Concerns::SetUserByToken
before_filter :add_allow_credentials_headers
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
before_action :configure_permitted_parameters, if: :devise_controller?
..yadayada...
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :phone
devise_parameter_sanitizer.for(:sign_up) << :username
devise_parameter_sanitizer.for(:sign_up) << :session
devise_parameter_sanitizer.for(:sign_in) << :phone
devise_parameter_sanitizer.for(:sign_in) << :username
devise_parameter_sanitizer.for(:sign_in) << :session
end
Y algunos modelos predeterminados para el usuario en el lado de los rieles.
Registro de rieles:
Started GET "/posts" for 192.168.83.26 at 2015-02-24 23:29:02 -0500
Processing by PostsController#index as JSON
Parameters: {"post"=>{}}
Filter chain halted as :authenticate_user! rendered or redirected
Completed 401 Unauthorized in 1ms (Views: 0.2ms | ActiveRecord: 0.0ms)
Si alguien puede proporcionar una idea que sería maravillosa. Me complace publicar más fragmentos según sea necesario.
En cuanto a mi caso, uso cookies para almacenar el token. Y siempre que hagamos métodos $auth
en nuestra aplicación angular, algunos de los métodos intentarán ir a la ruta de diseño que haya definido en su enrutador Rails y hacer coincidir / validar el token que está almacenado en cualquiera de las solicitudes del encabezado. (¡cada vez que intenta hacer una solicitud http!) revise sus encabezados de solicitud usando el inspector de su navegador si contienen uid
o auth_token
si va a validar a través de GET
/validate_token
( https://github.com/lynndylanhurley/devise_token_auth# uso-tldr ))
Como no mencionó su ruta, podemos asumir /auth
.
Y esa solicitud de $http
provista por $auth
debe contener un token para ser autenticado, es el Dispositivo de Rails, y capturarlo y almacenarlo en las cookies del navegador siempre que hagamos $auth.submitLogin()
.
Aquí está el ejemplo de cómo funciona en mi proyecto anterior.
app.factory(''authInterceptor'', [''$q'', ''ipCookie'', ''$location'', function($q, ipCookie, $location) {
return {
request: function(config) {
config.headers = config.headers || {};
if (ipCookie(''access-token'')) {
config.headers[''Access-Token''] = ipCookie(''access-token'');
config.headers[''Client''] = ipCookie(''client'');
config.headers[''Expiry''] = ipCookie(''expiry'');
config.headers[''Uid''] = ipCookie(''uid'');
}
return config;
},
responseError: function(response) {
if (response.status === 401) {
$location.path(''/login'');
ipCookie.remove(''access-token'');
}
return $q.reject(response);
}
};
}])
Y configure el formato del token para que se vea así (o personalizado según lo necesite)
$authProvider.configure({
tokenValidationPath: ''/auth/validate_token'',
signOutUrl: ''/auth/sign_out'',
confirmationSuccessUrl: window.location.href,
emailSignInPath: ''/auth/sign_in'',
storage: ''cookies'',
tokenFormat: {
"access-token": "{{ token }}",
"token-type": "Bearer",
"client": "{{ clientId }}",
"expiry": "{{ expiry }}",
"uid": "{{ uid }}"
}
});
No olvides ipCookie
(búsqueda de angular-cookie
lugar de angular-cookies
) en el Interceptor, ya que esta es la biblioteca de cookies que usa ng-token-auth para la administración de cookies.
Comente a continuación con preguntas si no me aclaro lo suficiente. :RE
Esta información puede ser relevante para usted.
Sospecho que el usuario con el que está intentando iniciar sesión no es válido. Cuando esto sucede, el encabezado de autorización está vacío y no se devuelve ningún token de acceso en la respuesta.
Esto sucede aquí: https://github.com/lynndylanhurley/devise_token_auth/blob/0d4de71/app/controllers/devise_token_auth/concerns/set_user_by_token.rb#L53
Como resultado, la solución fue bastante simple. Parece que en la mayoría de los ejemplos que todos proporcionan, no permiten access-token
, junto con todos los otros encabezados CORS.
Usamos rack-cors para esto, en la parte inferior de config.ru
:
require ''rack/cors''
use Rack::Cors do
# allow all origins in development
allow do
origins ''*''
resource ''*'',
:headers => :any,
:expose => [''access-token'', ''expiry'', ''token-type'', ''uid'', ''client''],
:methods => [:get, :post, :delete, :put, :options]
end
end
Y luego en ApplicationController.rb:
before_filter :add_allow_credentials_headers
skip_before_filter :verify_authenticity_token
before_filter :cors_preflight_check
after_filter :cors_set_access_control_headers
def cors_set_access_control_headers
headers[''Access-Control-Allow-Origin''] = ''*''
headers[''Access-Control-Allow-Methods''] = ''POST, GET, PUT, DELETE, OPTIONS''
headers[''Access-Control-Allow-Headers''] = ''Origin, Content-Type, Accept, Authorization, Token''
headers[''Access-Control-Max-Age''] = ''1728000''
end
def cors_preflight_check
if request.method == ''OPTIONS''
headers[''Access-Control-Allow-Origin''] = ''*''
headers[''Access-Control-Allow-Methods''] = ''POST, GET, PUT, DELETE, OPTIONS''
headers[''Access-Control-Allow-Headers''] = ''X-Requested-With, X-Prototype-Version, Token''
headers[''Access-Control-Max-Age''] = ''1728000''
render :text => '''', :content_type => ''text/plain''
end
end
def add_allow_credentials_headers
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#section_5
#
# Because we want our front-end to send cookies to allow the API to be authenticated
# (using ''withCredentials'' in the XMLHttpRequest), we need to add some headers so
# the browser will not reject the response
response.headers[''Access-Control-Allow-Origin''] = request.headers[''Origin''] || ''*''
response.headers[''Access-Control-Allow-Credentials''] = ''true''
end
Quizás es demasiado tarde
Pero el problema es porque no puedes tener la autenticación en las cookies (solo Android). Por lo tanto, puede intentar usar localStorage para guardar su información de sesión (en iOS y Android)
p.ej
.config(function($authProvider) {
$authProvider.configure({
apiUrl: ''http://myprivateapidomain/api'',
storage: ''localStorage''
});
})
Puede leer más en el número específico de la documentación: https://github.com/lynndylanhurley/ng-token-auth/issues/93
un poco tarde, pero para cualquiera que intente usar ng-token-auth en una aplicación Ionic, lo que hice para que funcione (en mi caso) fue establecer la siguiente configuración en mi módulo:
app.config([''$httpProvider'', function($httpProvider) {
$httpProvider.defaults.withCredentials = true;
}]);
(No estaba enviando ninguna cookie en mi solicitud http)