Grails: Expose LoginController for programmatic login - web-services

So I am working on a Grails/Flex toy project. I have a controller(LoginController) that I am using to perform backend authentication on my Flex app. However, I have been unable to "find" my controller. What I mean by that is I get a HTTP Status 404 error when trying to access
http://localhost:8080/OrlandoGrails/LoginController/login.json
Here is my sad, sad little controller as it is in its proof-of-concept state.
package orlandograils
class LoginController {
static allowedMethods = [login: "POST", login: "GET"]
def login(String username, String password )
{
return "Hello"
}
}
I've seen the documentation concerning RESTful services, but they always seem to concern a domain object which I don't have. In any case, I have also added this to my UrlMappings.groovy file
"/LoginController/login.json"(resource:"LoginController")
Any help on what I'm doing horribly wrong would be greatly appreciated. Also, is there a way to list Grails routes like one can with RoR or Symfony2?
Also, while the bulk of my services will be over the amf channels, my authentication is occurring over http.

It isn't entirely clear what you are trying to accomplish but one problem with your sample is that in your URL mapping you are specifying the name of a controller as your resource, which doesn't make sense. That could be a domain class, but not a controller.
If all you want to do is map a url to particular action in the controller you can do something like this in UrlMappings.groovy...
"/LoginController/login.json"(controller: 'login', action: 'login')
Normally you wouldn't have "Controller" in the url so something like this would be more common...
"/login/login.json"(controller: 'login', action: 'login')
From the little code snippet it also isn't clear what role you want JSON to play. Maybe you just want something like this...
"/login"(controller: 'login', action: 'login')
If you can further describe what you are trying to accomplish I can clarify.

In regards to getting a listing of routes (e.g. URL Mappings) you can run grails url-mappings-report
Also note to modify url-mapping to look like:
"/LoginController/login.json"(controller: "login", action: "login")
If resource is used then default action methods has to be show, create, update and delete
//Using resource: would look for a show() action method for a GET
//request which you don't have in your case. And, note name of controller used
//is login instead of LoginController
"/LoginController/login.json"(resource: "login")
As far as the 404 is concerned it's looking for a corresponding view called "hello.gsp" If you want to render text then use:
render text: 'hello'

The original post includes this:
package orlandograils
class LoginController {
static allowedMethods = [login: "POST", login: "GET"]
def login(String username, String password )
{
return "Hello"
}
}
The allowedMethods property there is bogus. Keys in a Map have to be unique. That code attempts to put the key login in the Map twice. If the intent is to say that the login method may be accessed via POST or GET then this makes sense...
static allowedMethods = [login: ['POST', 'GET']]
The code as written is valid, but it doesn't do what it was probably intended to do. That Map will evaluate to only have 1 value associated with the login key. That doesn't have anything to do with Grails, that is just standard Map behavior.
$ groovysh
Groovy Shell (2.1.9, JVM: 1.7.0_45)
Type 'help' or '\h' for help.
-------------------------------------------------------------------------------
groovy:000> [login: 'GET', login: 'POST']
===> {login=POST}
groovy:000>
Notice that the expression evaluates to a Map with the value "POST" associated with the login key.

Related

What is the best approach of using django and ajax?

I'm now working on my first big project and can't understand how to use Django with ajax.
On my website there are several services which works separately and are written on javascript, but soemtimes I have to send some information to the server.
Also I have custom admin interface which contains of different changing database operations. All these actions should be done without reloading the page (using ajax post and get requests).
So, I think I have two ways of doing it:
Using ajax and classic Django views for each operation.
Using ajax and integrated into my website Django REST Framework API methods.
The stumbling block is that I wouldn't use this API methods from any other types of clients, just call them from users' browsers via ajax. What is the best approach in my situation? It seems to me that the second way is more "serious", but I don't have much experience of making projects like this and can't speak directly.
You don't need to integrate REST. You can do ajax call to normal view like you do with user interaction. The view can return http response or JSON or whatever you need. If you would like to change somethink in DOM without refreshing page I can sugest HTMX (https://htmx.org/)
standard ajax call to get some json:
let datas = {id: $(this).val(),};
$.ajax({
url: "{% url 'to_your_view' %}",
type: "POST",
data: datas,
success: function (json) {
console.log(json);
},
error: function (xhr, errmsg, err) {
console.log(xhr.status + ": " + xhr.responseText);
}
});
and in view:
def to_your_view(request):
if request.method == "POST":
id = request.POST.get('id', 0)
if id != 0:
return HttpResponse(json.dumps(100), content_type="application/json")

Load protected image from API

I am using EmberJS along with ember-simple-auth and ember-data to authenticate and retrieve data from my API. One of my models contains properties that point to image URLs. I'd like to display these images in my app. I can do this using
<img class="thumbnail" src="{{user.thumbnail}}" />
The problem is that the images are protected and need an "Authorization" header to be set without which the API returns a 401. I thought about adding the token to the URL as a query parameter and modifying the API to accept it but it seems like a bad idea because the auth tokens will be present in the logs. Is there an EmberJS way of retrieving an image from a secured API?
EDIT based on your comment:
This is a server side solution so it would leave your ember code the way it is.
The approach is to never send the actual token with the images but use the token on the server to generate session specific image urls.
This way you never expose the absolute paths to your images but rather create relative urls that resolve to the absolute ones. You can use the session token as a key to an encryption algorithm like md5 and create the relative urls which would hide the sensitive information (such as the token) from the client, thus you would never send the token as the query parameter.
Note that this does mean that if the user is logged in and shares those image links, the images would be visible to anybody using the link until the user logs out (and his session is destroyed).
Previous suggestion
You could make a small component that does this for you where you pass in the url and either also pass the token or get it through an auth service. Then you use a computed property to combine the two. Here's a rough example:
// components/auth-img.js
export default Ember.Component.extend({
// passed in
class: '',
url: '',
token: '',
// local
tagName: 'img',
classNameBindings: ['class'],
attributeBindings: ['src'],
src: Ember.computed('url', 'token', function() {
let { url, token } = this.getProperties('url', 'token');
// combine your url and token and return
return // ...
})
});
And usage:
{{auth-img class="thumbnail" url=user.thumbnail}}

Loopback angular sdk unable to login

I'm trying to use loopback angular SDK to login but instead I'm getting back a 401 unauthorized response.
User.login({ rememberMe: true }, {email: $scope.user.email, password: $scope.user.password})
.$promise
.then(function() {
var next = $location.nextAfterLogin || '/';
$location.nextAfterLogin = null;
$location.path(next);
})
.catch(function(x) {
$scope.authError = 'Wrong Credentials';
});
};
Also i can see the user with the given credentials in the datasource that I've defined for the User model.
So basically, I have a boot script that creates a default user
User.create([{
username: 'admin',
email: 'xxxx#gmail.com',
password: 'admin'
}], on_usersCreated);
And I also have created a custom User model that extends the built-in User model.
Why am I getting a 401 unauthorized response when trying to login? I have even tried to login via the explorer, but with no success.
Update:
I debugged the build-in User model and the login method; and it seems that it cannot find the user with the given email. I can see it though in the mongodb database.
Inspect the ACL records of User model, starting you app in debug mode and viewing console: DEBUG=loopback:security:acl slc run.
I don't see anything wrong with your code. Are you sure the values you're passing into the function are correct? Try logging $scope.user.email and $scope.user.password before calling User.login.
See my new example here: https://github.com/strongloop/loopback-getting-started-intermediate/blob/master/client/js/services/auth.js#L6-L15
The tutorial part is not complete, you can look around the source code to get an idea of what you're doing different.

Omniauth - choose provider dynamically

Say I have a restful resource, UserSession
> POST /user_sessions.json
{
"user_session": {
"user": {
"some_key": "some_value",
"some_other_key": "some_other_value"
}
}
}
I'd like to choose the provider in the UserSessions#create based on the params supplied, rather than using the /auth/:provider OmniAuth normally uses. Is it possible to do this?
i am using a technique to set some omniauth options into the user-session.
i guess that this might work for your solution as well. you still have use the /auth/:provider routes though!
so i am basically linking all login urls to my auth_path
# routes.rb
get '/auth/login/:provider', to: 'sessions#auth', as: :auth
once i extract the data and put it into the session, i redirect the user to the right login path. in your case, it would need to extract the data from the params and then redirect:
# sessions_controller.rb
def auth
session[:omniauth_keys] = Usergroup.omniauth_keys(params[:provider], request)
redirect_to "/auth/#{params[:provider]}"
end

In Ember.js, how do you make requests to an API that are outside of the REST convention?

I would like to request a 'reset password' endpoint e.g GET -> user/password/reset on an API. What is the best way to map this request in ember.js? It doesn't seem appropriate to setup a full ember.js model for this kind of request, as it doesn't have a proper ID and is not really a request for a record, but a triggered event with a success/fail response. Am I incorrectly implementing the REST convention or is there another way to do this?
You can use a simple ember-object to represent password reset and then basic ajax. Something like this:
App.User.reopenClass({
resetPassword: function(subreddit) {
return $.getJSON("user/password/reset").then(
function(response) {
console.log('it worked');
return true;
},
function(response) {
console.log('fail');
return false;
}
);
}
});
See http://eviltrout.com/2013/03/23/ember-without-data.html
That said, this could be a sign that the API endpoint should change. Ideally GET requests should not have side effects, so a GET that resets a password is not recommended. If you think of reset as a password reset request, the reset password endpoint that makes the most sense is POST -> user/password/reset to create a new request.