I'm using a stack consisting of Rails with Grape (for API stuff) and Devise (for user stuff), and Ember with Ember CLI and Ember Simple Auth. I want to implement authorization using the DeviseAuthenticator exposed by Simple Auth. My login controller looks like this:
// app/controllers/login.js
import Ember from 'ember'
export default Ember.Controller.extend({
session: Ember.inject.service('session'),
actions: {
authenticate () {
let {identification, password} = this.getProperties('identification', 'password')
this.get('session').authenticate('authenticator:devise', identification, password).catch(reason => {
console.log(reason.error || reason)
})
}
}
})
and my Devise authenticator setup:
// app/authenticators/devise.js
import Devise from 'ember-simple-auth/authenticators/devise'
export default Devise.extend({
serverTokenEndpoint: 'http://localhost:4200/api/v1/users/sign_in',
resourceName: 'user',
crossOriginWhiteList: ['http://localhost:4200/']
})
For development purposes, I've commented out the error! "401 Unauthorized", 401 unless authenticated part in my Grape config (that's another problem though) just to see if it even works, but it throws this:
POST http://localhost:4200/api/v1/users/sign_in 405 (Method Not Allowed)
I have no idea what to do, and as such would appreciate some help. If I can post more code from other files, I'd be happy to, just tell me.
Found out that my devise routes are at /users/sign_in, not at /api/v1/users/sign_in.
Related
I have a problem with 'domain' => env ('SESSION_DOMAIN', null) in the session.php file. When set SESSION_DOMAIN value in .env file, for example
SESSION_DOMAIN=mysite.test
login don't works and there seems to be a middlaware.
If not set this parameter, login work fine, therefore when I call api protected route with sanctum maiddleware ex.
Route::middleware(['auth:sanctum'])->group(function () {
Route::get('/myroute', function () {
return 'hello world!';
});
});
I have unauthenticated response.
If use web.php file route and insert the same function:
Route::middleware(['auth:sanctum'])->group(function () {
Route::get('/api/myroute', function () {
return 'hello world!';
});
});
with api prefix, its works fines.
I followed laravel 8.x sanctum documentation https://laravel.com/docs/8.x/sanctum. In laravel projects 7.* without jetstream I had no problem.
There's any suggest or explaination for this phenomenon.
Any explanation would be helpful for me! Many Thanks.
I ran into a similar issue where I could not authenticate any API request from my frontend. Turns out the generated Kernel.php did not include the Sanctum middleware for session cookies by default - you have to add it manually in your app/Http/Kernel.php:
'api' => [
EnsureFrontendRequestsAreStateful::class, // <- Add and import this middleware
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
After doing this API requests from my frontend are working again. Maybe this resolves your issue as well.
Question
How would we test a Doorkeeper oauth2 implementation for a Zapier cli app?
Background
I have a Rails 3 app. I am trying to create a Zapier client for the application and I decided to use OAuth. Thus I configured doorkeeper to generate a JWT. All looks good, I am able to authorize and get token using the redirects.
I am not sure how to test the app purely through the console. Wouldn't it require some way to authorize using username/password?
I got an app generated from the template with some minor differences.
it('can fetch an access token', (done) => {
const bundle = {
inputData: {
// In production, Zapier passes along whatever code your API set in the query params when it redirects
// the user's browser to the `redirect_uri`
code: 'one_time_code',
subdomain: 'ducks'
},
environment: {
CLIENT_ID: process.env.CLIENT_ID,
CLIENT_SECRET: process.env.CLIENT_SECRET
}
};
appTester(App.authentication.oauth2Config.getAccessToken, bundle)
.then((result) => {
result.access_token.should.eql('a_token');
result.refresh_token.should.eql('a_refresh_token');
done();
})
.catch(done);
});
results in something like this:
1) oauth2 app can fetch an access token:
Got 401 calling POST https://ducks.<domain>.com/oauth/token, triggering auth refresh.
What happened:
Starting POST request to https://ducks.<domain>.com/oauth/token
Received 401 code from https://ducks.<domain>.com/oauth/token after 1425ms
Received content "{"error":"invalid_request","error_description":"The request is missing a required parameter, include"
Got 401 calling POST https://ducks.<domain>.com/oauth/token, triggering auth refresh.
Which should be because the user is not logged in the request made in the test console...
How can I make the user login? Or should the tests be changed?
I'm using rails to create an API that is consumed by angularjs.
I'm using the gems devise, devise_token_auth and the angularjs module ng-token-auth to manage the sessions of my application. I have my app with default configuration.
I have two problems with this modules.
First, when I log in with a real account, I get logged in the front end and see the home page as is supposed to, but when I load an api Url that needs authentication I get 404 Unauthorized Error unless I refresh a couple times the home page (where i just logged in).
My second problem, that I believe is related, is that when I'm logged in both server side and client side, and then I sign out on client side I don't get signed out server side. I tested it by loading the same Api Url that needs authentication and before and after I sign out I still receive the json data and the current_user variable still contains the logged user.
This are my controllers for /login and /logout.
var app = angular.module('app', ['ui.router', 'templates', 'ng-token-auth']);
app.controller('LoginController', function($scope, $auth, $state) {
$scope.login = {};
$scope.submitLoginForm = function(loginCredentials) {
$auth.submitLogin(loginCredentials).then(function(resp) {
//console.log('logged in successfully');
$state.go('loginRequired.index');
}).catch(function(resp) {
// handle error response
});
};
});
app.controller('LogoutController', function($scope, $auth, $state, $http) {
$auth.signOut().then(function() {
//console.log("User logged out");
$state.go('login');
}).catch(function() {
alert("Error");
});
});
This could be caused because you have more than one devise scope. What do you have in your config/routes.rb file for mounting devise? devise_for, devise_scope, mount_devise_token_auth_for, etc
If you add a Warden callback inside, file: config/initializers/devise.rb
example:
Warden::Manager.before_logout do |user,auth,opts|
# opts[:scope] could be :user, :api_user, etc
end
You will see different user scopes.
I have an ember-cli app that uses ember simple auth(ember-simple-auth-devise) add on for authentication. I need to change the token end point of my authorizer to
http://example.com/api/v1/users/sign_in.
In my environment.js file I have added
ENV['simple-auth'] = {
authorizer: 'simple-auth-authorizer:devise',
crossOriginWhitelist: ['http://example.com'] //For CORS
};
ENV['simple-auth-devise'] = {
serverTokenEndPoint : 'http://example.com/api/vi/users/sign_in'
}
But on logging in its still posts the credentials to the default url i.e.
http://example1.com/users/sign_in.
How can I change this url to use my rails app endpoint.
Maybe the problem is that the property key is serverTokenEndpoint with a lowercase p. If you go to API docs you can see the correct property name.
I made a project with angular 1.0.8 and devise last version, on Rails 4, all worked great, devise was sending respond 401 when I did request to the api without been logged in.
the interceptor was getting the 401 and handle it the way I wanted.
but then decide to make the upgrade to the last stable version 1.2.1 and all worked great (only needed to change the interceptor, instead of return a function, returned an object), but for some reason devise now does a redirect to the sign_up page instead of send the 401 respond, not sure whats going on because I test with a controller responding with a status: :unauthorized, and my interceptor did caugth it just fine. someone already had this problem when migrating to 1.2.1? as I said the only code I change was the interceptor it self (it works fine with my 401 responds).
all I get is a 302 Found status code.
the interceptor code:
.config(function($httpProvider){
var interceptor = function($q, $location, $rootScope) {
return {
'responseError': function(rejection) {
if (rejection.status == 401) {
$rootScope.$broadcast('event:unauthorized');
console.log('got you trying to do something illegal...')
return rejection;
}
return $q.reject(rejection);
}
};
};
$httpProvider.interceptors.push(interceptor);
})
UPDATE
So after a while trying I realize to get a 401 using angularjs 1.2.1 and Devise I need to:
Add the .json format to all the services url(that needed authentication, eg: api/events/:id.json).
Make sure the config.navigational_formats = [] on config/initilizers/devise.rb didn't had the :json in its array.
And make sure the config.http_authenticatable_on_xhr = true was set to true.
But I still have the question, why on Angular.js 1.0.8 this worked even with navigational_formats array having the :json and services dont having .json?
Its the way its now the right way?