Symfony2.8 API + Login Form - rest

I have a website that uses Symfony2.8; I am working on a mobile app that would use the same project as the backend so I need to support token based authentication as well as regular login forms. All resources I've found talk about API only authentication not API(token based) and form. Anyone has any ideas how to accomplish this?
I am using FOSUserBundle if that matters.

You can do it by using custom Authenticators for each case.
Symfony 2.8 introduced Guard, which makes it's relatively easy to create custom Authenticators.
Basically you create 2 custom Authenticators , which essentially means creating 2 Services.
FormLoginAuthenticator -> app.form_login_authenticator
ApiTokenAuthenticator -> app.api_token_authenticator
Once these services are created, you just have to register those as Authenticators
in app/config/security.yml
security:
...
main:
anonymous: ~
knpu_guard:
authenticators:
- app.form_login_authenticator
- app.api_token_authenticator
entry_point: app.form_login_authenticator
Obviously it's upto you to implement those Services, but Symfony Docs does provide a decent starting point for you to start .
Check these links for the same :
How to Create a Custom Authentication System with Guard
How to Use Multiple Guard Authenticators
https://knpuniversity.com/screencast/guard ( provides fully working example + tutorial )

Related

handling the The CSRF token in symfony's forms when in public REST context

I'm developer my first symfony (3) app. it is a REST service publicly accessible.
I'm doing this using FOSRestBundle.
I'll have to ad some admin forms soon or later, and I'll probably want to create them directly (without passing by the extra work of consuming my own web services)
I wonder how to handle the CSRF token in this case. I see different solutions:
globally deactivate the CSRF token : I don't want to do this
create two set of forms, one with the token activated : form my admin forms, the other one for the REST API. => in this case, the rest API can't have a fallback _format=html
find a way to give the api consumer an auth, with an API_GROUP, and disable the token for this group
it seem to me the best solution, but I don't know how to do it transparently, without affecting the auth of my future admin, and without needing to give credentials in the REST request.
use an event listener in order to hack symfony's auth mechanism and give an auth if a call is made to the REST API (all but _format=html)
Which one of this (or other) solution seem the best to you, and how would you code it?
I found a way, perhaps not the best one, but it works :
$_format = $request->attributes->get('_format');
if ('html' == $_format) {
$form = $this->createForm(ItopInstanceUserType::class, $itopInstanceUser);
} else {
$form = $this->createForm(ItopInstanceUserType::class, $itopInstanceUser, ['csrf_protection' => false]);
}
For me, forget CSRF token managed by yourself, check subjects like Oauth authentication.
Take a look here: https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/blob/master/Resources/doc/index.md
FOSOAuthServerBundle works perfectly with FOSRestBundle.

How to write REST Web services in Laravel 5.2?

I am creating api for mobile app in laravel 5.2 version but now I am facing one problem. Problem is that in my routes.php I am created routes for my website. Now my question is if I start creating api for mobile for that I have to create new routes for mobile api Or I can use same routes for RESTapi also?
In Laravel 5.2 I have to add any webservices libraries or not? If yes, Please suggest me how to use RESTapi in Laravel 5.2? Please help.
My routes.php
Route::auth();
Route::get('/', 'Auth\AuthController#login');
Route::get('admin/users', 'UserController#getUsers');
Route::get('admin/users/add', 'UserController#addUser');
If your routes an their inside logic returns json response, Its not necessary to create new routes, But if your routes does not returns json response, you must write new routes.
For having better APIs, json-hal, jsend or json-api conventions may help you.
Your api routes can coexist with your regular web routes. It's customary, however, to separate them, typically by a subdomain (https://api.yoursite.com), or at least a path (https://yoursite.com/api/v1).
Also, api version number is often included, as in my last example.
As for a package to develop apis in Laravel, have a look at Dingo. It's very complete, provides its own router, versioning, security, etc.
You have different middleware in laravel. By default you should have "web" middleware activated. It is either directly in your routes.php, in your controler constructor OR in the RouteServiceProvider.php
You wouldn't use web middleware for an api / restful service, therefore you should use another middleware ( e.g. "api" middleware which throttles requests to only allow max. 60 requets per minute etc. )
Typically you group your api requests
Route::group(['prefix' => 'api/v1'], function()
{
...
}
to strictly divide them from your application. You can then also easy change to v2 for example if you plan many releases
Update
if your api logic follows your business logic then you could aswell just watch for ajax calls and return json
public function index(Request $request) {
// do stuff here
if($request->ajax()) {
// return json
}
// return view
}

get customfield value for jira issue using JIRA SOAP API

I want to get the values of all custom fields for a particular JIRA issue using SOAP API. I have a custom field named 'Phase' having value Decision Pending for a JIRA issue JIRA-123.
I am using JIRA 5.1.3.
I am able to get all the properties of JIRA issue using SOAP API except the value of the custom field for above issue.
I tried following code, but I am not able to use ComponentManager in my code
IssueManager issueManager = ComponentManager.getInstance().getIssueManager();
CustomFieldManager customFieldManager = ComponentManager.getInstance().getCustomFieldManager();
Issue issue = issueManager.getIssueObject("JIRA-123");
CustomField customField = customFieldManager.getCustomFieldObjectByName("Phase");
Object customFieldValue = issue.getCustomFieldValue(customField);
I would highly appreciate if anyone can provide correct approach.
The SOAP API is deprecated by 5.1.3. I suggest you use the REST API - it is both more easy to use and implement.
What is REST?: read here. The basic idea is to bind HTTP request types to actions, it's quite obvious - check this table for a quick run-in.
Jira has a powerful REST API that you can use. This is the main documentation of the current release.
What do you need to do in some high-level steps?:
Set-Up some type of authentication with your JIRA instance. Be it:
Baisc - example
OAuth - example
Get a list of all fields via the API:
The /rest/api/2/field' [method returns a list of all fields][6] - both System and Custom.
Then when you identify the exact field use/rest/api/2/customFieldOption/{id}` to get the full
representation of the Custom Field Option.
I recommend you use a tools like Chrome REST Console ,or anything similar that you can easily make requests with, to get to know the API. The bonus is that you don't need to setUp authentication if you're logged in through the same browser. Your user will require full admin access though.
This is the root of all JIRA REST API docs. Check it out.
If you're doing this in PHP I would personally recommend using some kind of library. I've used
Guzzle (in a CakePHP environment) for this exact task and it turned out very well.
I'm not sure of how do you use the soap API, here is example of using it via the PHP-SOAP:
#!/usr/bin/php -q
<?php
$soapClient = new SoapClient("https://jira.com/rpc/soap/jirasoapservice-v2?wsdl");
$token = $soapClient->login('user', 'password');
$myIssue = $soapClient->getIssue($token,"TES-13");
print_r($myIssue); // all of the issue details
print_r($myIssue->customFieldValues); // get all custom fields
foreach ($myIssue->customFieldValues as $customFieldValue) {
// search for the right custom field
if ($customFieldValue->customfieldId == 'customfield_10402') {
echo $customFieldValue->values[0];
die();
}
}
?>
In case you want to use any other API, have a look at the JIRA Remote API Reference.
A remark regarding the REST and SOAP APIs -To quote from Jira's site the SOAP API "Supported but no future development". The Rest API is still a bit new and there are things you can't yet do with the REST API (example), and can be done easily using the SOAP API.

ASP.NET Web API Authorization with AuthorizeAttribute

Using the new ASP.NET Web API beta. I can not seem to get the suggested method of authenticating users, to work. Where the suggested approach seems to be, to add the [Authorize] filter to the API controllers. For example:
[Authorize]
public IEnumerable<Item> Get()
{
return itemsService.GetItems();
}
This does not work as intended though. When requesting the resource, you get redirected to a login form. Which is not very suitable for a RESTful webapi.
How should I proceed with this? Will it work differently in future versions?, or should I fall back to implementing my own action filter?
Double check that you are using the System.Web.Http.AuthorizeAttribute and not the System.Web.Mvc.AuthorizeAttribute. This bit me before. I know the WebAPI team is trying to pull everything together so that it is familiar to MVC users, but I think somethings are needlessly confusing.
Set your authentication mode to None:
<authentication mode="None" />
None Specifies no authentication. Your application expects only anonymous users or the application provides its own authentication.
http://msdn.microsoft.com/en-us/library/532aee0e.aspx
Of course then you have to provide some sort of authentication via headers or tokens or something. You could also specify Windows and use the built in auth via headers.
If this site is mixed between API and actual pages that do need the Forms setting, then you will need to write your own handling.
All the attribute does is return an HttpUnauthorizedResult instance, the redirection is done outside of the attribute, so its not the problem, its your authentication provider.
Finally, I've found a solution at:
ASP.NET MVC 4 WebAPI authorization
This article shows how you can fix this issue.
You are being redirected to login page because forms authentication module does this automatically. To get rid of that behavior disable forms authentication as suggested by Paul.
If you want to use more REST friendly approach you should consider implementing HTTP authorization support.
Take a look at this blog post http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/
ASP.NET 5 Introduced the new Microsoft.AspNet.Authorization System which can secure both MVC and Web API controllers.
For more see my related answer here.
Update:
At that time 2 years ago it was Microsoft.AspNetCore.Authorization.
As #Chris Haines pointed out. now it resides on
Microsoft.AspNetCore.Authorization.
From .NET core 1.0 to 2.0 many namespaces have been moved i think.
And spread functionality between .net classic and core was obscure.
That's why Microsoft introduced the .net standard.
.net standard
Also, look at my answer for:
How to secure an ASP.NET Web API
There is a NuGet package I have created which you can use for convenience.
If you're using a Role, make sure you have it spelled correctly :
If your role is called 'Administrator' then this - for instance will not work :
[System.Web.Http.Authorize(Roles = "Administator")]
Neither will this :
[System.Web.Http.Authorize(Roles = "Administrators")]
Oops...
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[Produces("application/json")]
[Route("api/[controller]")]
public class CitiesController : Controller
{
[HttpGet("[action]")]
public IActionResult Get(long cityId) => Ok(Mapper.Map<City, CityDTO>(director.UnitOfWork.Cities.Get(cityId)));
}
Use
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Filter with authentication type

Zend Framework Twitter Service Requires Authentication for UserTimeline?

I am using the Zend_Service_Twitter class to retrieve my userTimeline, however since August, I am no longer able to use Basic Authentication. This is perfectly fine, since userTimeline does not require authentication at all.
Strange enough, Zend_Service_Twitter thinks userTimeline requires full authentication (using oAuth tokens) to retrieve an unprotected twitter userTimeline. Is there a way around this that allows me to use all the normal userTimeline twitter api variables.
Thanks
I recently ran into this same issue - however, instead of trying to fix the broken Zend class, I just used the Search API.
$searchString = 'from:leeked';
$twitterSearch = new Zend_Service_Twitter_Search('json');
$this->twitter = $twitterSearch->search($searchString, array('rpp' => 15));