14

Guys If My Question is not clear please comment below.

Basic HTTP Authentication for REST API in flask+angularjs

I just want to login to the flask-rest-api in angularjs, I don't know how to send the login info (username and password)to flask-rest-api. In this app There is one table after successfully login and it will load the data. Here we are not using any data-base but username and password is hard-coded in rest-server code. and username="admin" and password="1234". When can modify, update, addNewData. I took this from this blog, here they are using in knockout, I am trying to in Angularjs

Login form

<div id="login" class="modal hide fade" tabindex="=1" role="dialog" aria-labelledby="loginLabel" aria-hidden="true">
        <div class="modal-header">
            <h3 id="loginLabel">Sign In</h3>
        </div>
        <div class="modal-body">
            <form class="form-horizontal">
                <div class="control-group">
                    <label class="control-label" for="inputUsername">Username</label>
                    <div class="controls">
                        <input ng-model="username" type="text" id="inputUsername" placeholder="Username">
                    </div>
                </div>
                <div class="control-group">
                    <label class="control-label" for="inputPassword">Password</label>
                    <div class="controls">
                        <input ng-model="password" type="password" id="inputPassword" placeholder="Password">
                    </div>
                </div>
            </form>
        </div>
        <div class="modal-footer">
            <button ng-click="submitData(username, password)" class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Sign In</button>
        </div>
    </div>

HTML Code Which call Login Model

<div class="navbar">
      <div class="navbar-inner">
        <a class="btn" data-toggle="modal" data-target="#login">Login</a>
      </div>
</div>

AngulurJS code

<script>

                    var app = angular.module('myApp', []);
                    app.controller('tasksCtrl', function($scope, $http) {
                        $scope.submitData=function(username, password){
                            var config={
                               params:{
                                   username:username, password:password
                               }
                            };
                        };
                        //$http.get("data.json")
                        $http.get("/todo/api/v1.0/tasks")
                        .success(function(response) {
                            console.log(response.tasks)
                            $scope.tasks = response.tasks;
                        });

                        $scope.editTask = function(task) {
                            $scope.selectedTask = task;
                        };
                        $scope.removeRow = function(task) {
                            $scope.tasks.splice(task, 1);
                        };
                        $scope.addNewTask = function() {
                            //$scope.tasks.push({title :$scope.task1,description: $scope.description1});
                            $scope.tasks.push({title: $scope.task1, description: $scope.description1});
                            $scope.task1 = '';
                            $scope.description1 = '';
                            //   $scope.tasks.push('dhsh');
                        };
                    });    
        </script>

REST-API-SERVER

import six
from flask import Flask, jsonify, abort, request, make_response, url_for, render_template 
from flask.ext.httpauth import HTTPBasicAuth

app = Flask(__name__, static_url_path="")
auth = HTTPBasicAuth()


@auth.get_password
def get_password(username):
    if username == 'admin':
        return '1234'
    return None


@auth.error_handler
def unauthorized():
    return make_response(jsonify({'error': 'Unauthorized access'}), 403)


@app.errorhandler(400)
def bad_request(error):
    return make_response(jsonify({'error': 'Bad request'}), 400)


@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)


tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]


def make_public_task(task):
    new_task = {}
    for field in task:
        if field == 'id':
            new_task['uri'] = url_for('get_task', task_id=task['id'],
                                      _external=True)
        else:
            new_task[field] = task[field]
    return new_task

@app.route('/')
@auth.login_required
def index():
   return render_template('index.html')

@app.route('/todo/api/v1.0/tasks', methods=['GET'])
@auth.login_required
def get_tasks():
    return jsonify({'tasks': [make_public_task(task) for task in tasks]})


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
@auth.login_required
def get_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    return jsonify({'task': make_public_task(task[0])})


@app.route('/todo/api/v1.0/tasks', methods=['POST'])
@auth.login_required
def create_task():
    if not request.json or 'title' not in request.json:
        abort(400)
    task = {
        'id': tasks[-1]['id'] + 1,
        'title': request.json['title'],
        'description': request.json.get('description', ""),
        'done': False
    }
    tasks.append(task)
    return jsonify({'task': make_public_task(task)}), 201


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
@auth.login_required
def update_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    if not request.json:
        abort(400)
    if 'title' in request.json and \
            not isinstance(request.json['title'], six.string_types):
        abort(400)
    if 'description' in request.json and \
            not isinstance(request.json['description'], six.string_types):
        abort(400)
    if 'done' in request.json and type(request.json['done']) is not bool:
        abort(400)
    task[0]['title'] = request.json.get('title', task[0]['title'])
    task[0]['description'] = request.json.get('description',
                                              task[0]['description'])
    task[0]['done'] = request.json.get('done', task[0]['done'])
    return jsonify({'task': make_public_task(task[0])})


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
@auth.login_required
def delete_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    tasks.remove(task[0])
    return jsonify({'result': True})


if __name__ == '__main__':
    app.run(debug=True)
7
  • Guys Please let me now If my question is not clear, I am new in rest-api and flask, please help on this question... Commented Jul 3, 2015 at 14:44
  • Guy, please drop some comments... Commented Jul 3, 2015 at 14:54
  • 4
    If I correctly understand your question, you are asking how to do Basic HTTP Authentication from AngularJS (or at least that's what your python Flask code is exposing). This link will have some info related to your question jasonwatmore.com/post/2014/05/26/… Commented Jul 7, 2015 at 15:12
  • @Boris Thanks for nice link, you are right I am searching Basic HTTP Authentication, but for REST API, the above link is not for rest api.. Commented Jul 8, 2015 at 3:41
  • @NeelabhSingh REST API is just some concept implemented on top of HTTP right? Commented Jul 8, 2015 at 10:13

2 Answers 2

1

The way you make basic authentication from client side is by supplying Authorization: Basic <encoded username:password> header in HTTP request.

encoded username:password is done in specific manner described below:

  1. Username and password are combined into a string "username:password"
  2. The resulting string is then encoded using the RFC2045-MIME variant of Base64, except not limited to 76 char/line[9]

So modify your rest calls to include above header in your Angularjs code or find a library to do that.

as @Boris mentioned in comments above, see this link http://jasonwatmore.com/post/2014/05/26/AngularJS-Basic-HTTP-Authentication-Example.aspx it has nice Angular service written to do just what you want

Sign up to request clarification or add additional context in comments.

Comments

0

You could try the simplest, least secure way of doing this, which is to pass the login information like this:

username:[email protected]

If you try it with any website it attempts to log in using whatever you provided. It might work in your environment.

As mentioned in the above article, you should really set up a Auth Service, which requires you to log in on the front end. It looks like you are not using routing, or angular-ui-router. With routing you can redirect people to the login route, before allowing them to access any of the other routes. This question has the answer I used to set up this behavior. And here's the example which shows certain routes are only accessible when authenticated.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.