How to have a secure API with symfony backend and WSSE auth & angular front end?

637 views Asked by At

I have my backend with Symfony2 (fosuserbundle, fosrestbundle, nelmio & wsse auth) and my frontend with Angular2.

I want secure this with WSSE auth headers. My salt is generate with Sf2 and my WSSE token too.

But how can i develop this linked to the frontend Angular2.

Look my code

BACKEND CONTROLLER (THAT'S WORK ON MY BACKEND!!! )

/**
 * Create a Token from the submitted data.<br/>
 *
 * @ApiDoc(
 *   resource = true,
 *   description = "Creates a new token from the submitted data.",
 *   statusCodes = {
 *     200 = "Returned when successful",
 *     400 = "Returned when the form has errors"
 *   }
 * )
 *
 * @param ParamFetcher $paramFetcher Paramfetcher
 *
 * @RequestParam(name="username", nullable=false, strict=true, description="username.")
 * @RequestParam(name="password", nullable=false, strict=true, description="password.")
 * @RequestParam(name="salt", nullable=false, strict=true, description="salt.")
 *
 * @return View
 */
public function postTokenAction(ParamFetcher $paramFetcher)
{

    $view = View::create();

    $userManager = $this->get('fos_user.user_manager');
    $user = $userManager->findUserByUsername($paramFetcher->get('username'));

    if (!$user instanceof User) {
        $view->setStatusCode(404)->setData("Data received succesfully but with errors.");

        return $view;
    }

    $factory = $this->get('security.encoder_factory');

    $encoder = $factory->getEncoder($user);
    $password = $encoder->encodePassword($paramFetcher->get('password'), $paramFetcher->get('salt'));

    $header = $this->generateToken($paramFetcher->get('username'), $password);
    $data = array('X-WSSE' => $header);
    $view->setHeader("Authorization", 'WSSE profile="UsernameToken"');
    $view->setHeader("X-WSSE", $header);
    $view->setStatusCode(200)->setData($data);

    return $view;
}

/**
 * Generate token for username given
 *
 * @param  string $username username
 * @param  string $password password with salt included
 * @return string
 */
private function generateToken($username, $password)
{
    $created = date('c');
    $nonce = substr(md5(uniqid('nonce_', true)), 0, 16);
    $nonceSixtyFour = base64_encode($nonce);
    $passwordDigest = base64_encode(sha1($nonce . $created . $password, true));

    $token = sprintf(
        'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"',
        $username,
        $passwordDigest,
        $nonceSixtyFour,
        $created
    );

    return $token;
}

}

FRONT END CONTROLLER (THAT'S FALSE - DON?T WORK AND HOW CAN I DEVELOP THIS ?)

.controller('SignInCtrl', function ($rootScope, $scope, $http, $cookies, Salt, Digest, envService) {

    var apiUrl = envService.read('apiUrl');

    $scope.username = null;
    $scope.password = null;

    $scope.getSalt = function (username, password) {
        var data = {
            username: $scope.username,
            password: $scope.password
        };
        // Get Salt
        Salt.get({username: username}, function (data) {
            var salt = data.salt;
            // Encrypt password accordingly to generate secret
            Digest.cipher(password, salt).then(function (secret) {
                // Display salt and secret for this example
                $scope.salt = salt;
                $scope.secret = secret;
                // Store auth informations in cookies for page refresh
                $cookies.username = $scope.username;
                $cookies.secret = secret;
                $cookies.salt = $scope.salt;
                // Store auth informations in rootScope for multi views access
                $rootScope.userAuth = {username: $scope.username, secret: $scope.secret, salt: $scope.salt};
            }, function (err) {
                console.log(err);
            });
        });
        $http({
            method: 'GET',
            url: apiUrl + 'v1/users/' + username + '/salt.json',
            data: JSON.stringify(data),
            headers: {
                'Content-Type': 'application/json'
            }
        }).then(function (response) {
                if (response.data) {
                    var salt = response.data.salt;
                    $scope.salt = salt;
                    var dataToken = {
                        username: $scope.username,
                        password: $scope.password,
                        salt: salt
                    };
                }
                $http({
                    method: 'POST',
                    url: apiUrl + 'v1/tokens.json',
                    data: JSON.stringify(dataToken),
                    headers: {
                        'Content-Type': 'application/json'
                    }
                }).then(function (response) {
                    if (response.data) {
                        console.log("Token found");
                        $window.sessionStorage.token = reponse.data;
                    }
                });

            },
            function (response) {
                delete $window.sessionStorage.token;
                $scope.msg = "Service not Exists";
                $scope.statusval = response.status;
                $scope.statustext = response.statusText;
                $scope.headers = response.headers();
            }
        );


    };
});

My json return WSSE Headers but how use this after ?

"UsernameToken Username="kamyexemple", PasswordDigest="5KIZPtZozkIw8fbj0wkgW234PJI=", Nonce="MDg3M2Q4NTZlZDA1YzU1ZQ==", Created="2016-12-18T13:50:56+01:00""

Name

1

There are 1 answers

0
Don Omondi On

Use https://github.com/FriendsOfSymfony/FOSOAuthServerBundle, for Client side Apps with a Symfony backend this with FOSUser and FOSRest really are what you need, tried and tested.