Shiro permission configuration and custom filter conflict - shiro

if I add a custom filter jwt to shiroFilterFactoryBean, the urlFilter.put("/helloworld","authc,rolse[user]"); is
Invalid.
Map<String,Filter> filterMap = new LinkedHashMap<>();
filterMap.put("jwt",new JWTFilter() );
shiroFilterFactoryBean.setFilters(filterMap);
Map<String,String> urlFilter = new LinkedHashMap<>();
urlFilter.put("/user/signin", "anon" );
urlFilter.put("/user/register", "anon" );
urlFilter.put("/**", "jwt" );
urlFilter.put("/helloworld", "authc,rolse[user]");

Order matters, you just need to stick the /** at the end of your map, see related warning in the documentation:
https://shiro.apache.org/web.html#web-ini-configuration

Related

Using Symfony Form component standalone with security-csrf - error on submission

I have a question regarding symfony/form using as a standalone component and security-csrf running with PHP build-in server. I hardly remember having such issue with the Symfony framework.
When setting symfony/form as a standalone component I tried this code for both v4.2 and v5.1 https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig. A rewrite of webmozart's example mentioned here https://symfony.com/doc/current/components/form.html
The csrf token is generated with twig-bridge, but when submitting the form - on calling$form->isValid() - invalid csrf error appears.
By default csrf protection is enabled, setting to false - the form submits.
Tried CSRF component with both setups with NativeSessionTokenStorage and SessionTokenStorage + Session of HttpFoundation.
Could you give any hint on what I'm doing wrong and where to look at?
P.S.
Code samples with csrf error on submission:
https://github.com/xmgcoyi/standalone-forms/tree/4.2+twig
https://github.com/liorchamla/pratique-symfony-form/tree/06-protection-csrf
UPD
The apps above work well, the problem was in browser storage filled with garbage.
Setting to false in $formFactory->createBuilder(FormType::class, null, ['csrf_protection' => false]) submits the form
This is a bit of a guess but the 4.2 linked repo has:
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$csrfTokenManager = new CsrfTokenManager();
Two token managers. One is used in the twig form engine and one is used in the form factory extension. Does not seem like a reasonable thing to do.
Here is an updated 5.1 working example. I stripped it down even more from your linked repo. But the only thing that I really changed was the token manager.
# index.php
require_once '../vendor/autoload.php';
$app = new App();
$app->run();
final class App
{
public function run()
{
$csrfGenerator = new UriSafeTokenGenerator();
$csrfStorage = new NativeSessionTokenStorage();
$csrfManager = new CsrfTokenManager($csrfGenerator, $csrfStorage);
$twig = new Environment(new FilesystemLoader([
'../templates',
'../vendor/symfony/twig-bridge/Resources/views/Form',
]));
$formEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig);
$twig->addRuntimeLoader(new FactoryRuntimeLoader([
FormRenderer::class => function () use ($formEngine,$csrfManager) {
return new FormRenderer($formEngine, $csrfManager);
},
]));
$twig->addExtension(new TranslationExtension());
$twig->addExtension(new FormExtension());
$formFactory = Forms::createFormFactoryBuilder()
->addExtension(new CsrfExtension($csrfManager))
//->addExtension(new ValidatorExtension($validator))
->getFormFactory();
$form = $formFactory->createBuilder()
->add('firstName', TextType::class)
->getForm();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$form->submit($_POST[$form->getName()]); // form
if ($form->isValid()) {
dump('form is valid');
}
}
echo $twig->render('index.html.twig', [
'form' => $form->createView(),
]);
}
}
The composer.json is simply:
{
"require": {
"symfony/form": "^5.1",
"symfony/twig-bridge": "^5.1",
"symfony/translation": "^5.1",
"symfony/security-csrf": "^5.1"
},
"require-dev": {
"symfony/var-dumper": "^5.1"
}
}
If you still have trouble then I would suggest tracking down where the sessions are stored and then verifying the that csrf token is being properly stored. It should look something like:
_csrf|a:1:{s:4:"form";s:43:"9v1tUNe3J3eYVOmEPwVdz5_iISfzBg8Qa9pLMV8tSN4";}
This was actually kind of an interesting exercise in using the twig system for standalone forms. Thanks.

how to access header in lumen routing file(web.php)

how to access header in routing file lumen ?
i want to use header parameters values as namespace in route group in web.php.
example :
$router->group(['namespace' => 'Request::header('version')'], function() use ($router)
{
$router->post('login', 'UserController#loginUser');
$router->post('test', 'UserController#testApi');
});
if request header version param v1 then it use v1 namespace,if v2 then use v2 namespace.something like versioning.
If you just want a way to grab the version from header, you can try putting Request as callback parameter as seen:
$router->get('/head', function(\Illuminate\Http\Request $request) {
return $request->header('version');
});
above should return whatever value you put as header with version key.
But I personally suggest you to try separating the route group for this. Say you'll have
$app->router->group([
'namespace' => 'App\Http\Controllers\Api',
'prefix'=> 'api/v1/',
'middleware' => ['jwt.auth', 'student_access_token']
], function ($router) {
require __DIR__.'/../routes/api.php';
});
and then for other version you just define the same on bootstrap/app.php directing to other route files. Hope it helps.

why don't work Facebook Login after march of 2017? [duplicate]

Because it's due date for graph api 2.2, I'm trying fix my graph api using v2.3
But I discover most api request response nothing when I use 2.3, but I can not found any update for this in the upgrade document. For example:
https://graph.facebook.com/v2.3/{$user_id}?date_format=U&fields=albums.order(reverse_chronological).limit(100).offset(0){id,count,name,created_time}
will return nothing if I use 2.3.
And I can't get user's birthday when I call:
https://graph.facebook.com/v2.3/{$user_id}
It's only return name and live location.
But in v2.2, it include birthday profile.
I use facebook SDK 3.2.2 because my php version is 5.3.
Is there any update that I don't know? Thanks.
I have found the problem myself. It's because the SDK 3.2.2. For facebook update (from the Changelog for API version 2.3):
[Oauth Access Token] Format - The response format of https://www.facebook.com/v2.3/oauth/access_token returned when you exchange a code for an access_token now return valid JSON instead of being URL encoded. The new format of this response is {"access_token": {TOKEN}, "token_type":{TYPE}, "expires_in":{TIME}}. We made this update to be compliant with section 5.1 of RFC 6749.
But SDK is recognize the response as an array(in the getAccessTokenFromCode function):
$response_params = array();
parse_str($access_token_response, $response_params);
if (!isset($response_params['access_token'])) {
return false;
}
return $response_params['access_token'];
This will not get user access token correctly, and you can't get user's data. So you should update this function to parse data as json:
$response = json_decode($access_token_response);
if (!isset($response->access_token)) {
return false;
}
return $response->access_token;
Then all of the function will work as usual.
Additionally, you must make similar changes to setExtendedAccessToken(). Otherwise, your app won't be able to extend access tokens. The code below demonstrates how to upgrade the function.
/**
* Extend an access token, while removing the short-lived token that might
* have been generated via client-side flow. Thanks to http://bit.ly/ b0Pt0H
* for the workaround.
*/
public function setExtendedAccessToken() {
try {
// need to circumvent json_decode by calling _oauthRequest
// directly, since response isn't JSON format.
$access_token_response = $this->_oauthRequest(
$this->getUrl('graph', '/oauth/access_token'),
$params = array(
'client_id' => $this->getAppId(),
'client_secret' => $this->getAppSecret(),
'grant_type' => 'fb_exchange_token',
'fb_exchange_token' => $this->getAccessToken(),
)
);
}
catch (FacebookApiException $e) {
// most likely that user very recently revoked authorization.
// In any event, we don't have an access token, so say so.
return false;
}
if (empty($access_token_response)) {
return false;
}
//Version 2.2 and down (Deprecated). For more info, see http://stackoverflow.com/a/43016312/114558
// $response_params = array();
// parse_str($access_token_response, $response_params);
//
// if (!isset($response_params['access_token'])) {
// return false;
// }
//
// $this->destroySession();
//
// $this->setPersistentData(
// 'access_token', $response_params['access_token']
// );
//Version 2.3 and up.
$response = json_decode($access_token_response);
if (!isset($response->access_token)) {
return false;
}
$this->destroySession();
$this->setPersistentData(
'access_token', $response->access_token
);
}

Laravel 5: POST without CSRF checking

It seems that Laravel 5 by default applies the CSRF filter to all non-get requests. This is OK for a form POST, but might be a problem to an API that POSTs DELETEs etc.
Simple Question:
How can I set a POST route with no CSRF protection?
Go to app/Http/Middleware/VerifyCsrfToken.php and then enter your routes(for which you want to disable csrf token) in the $except array.
for example:
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'/register'
];
}
You can exclude URIs from CSRF by simply adding them to the $except property of the VerifyCsrfToken middleware (app/Http/Middleware/VerifyCsrfToken.php):
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
class VerifyCsrfToken extends BaseVerifier
{
/**
* The URIs that should be excluded from CSRF verification.
*
* #var array
*/
protected $except = [
'api/*',
];
}
Documentation: http://laravel.com/docs/5.1/routing#csrf-protection
My hack to the problem:
CSRF is now a "middleware" registered globally in App\Http\Kernel.php. Removing it will default to no CSRF protection (Laravel4 behavior).
To enable it in a route:
Create a short-hand key in your app/Providers/RouteServiceProvider.php :
protected $middleware = [
// ....
'csrf' => 'Illuminate\Foundation\Http\Middleware\VerifyCsrfToken',
];
You can now enable it to any Route:
$router->post('url', ['middleware' => 'csrf', function() {
...
}]);
Not the most elegant solution IMO...
just listen to this. Just before 30 minute i was facing this same problem. Now it solved. just try this.
Goto App -> HTTP-> Kernel
open the kernel file.
there you can see : \App\Http\Middleware\VerifyCsrfToken::class,
just disable this particular code using //
Thatz it! This will work!
So that you can remove the middleware from the API calling (if you want so..)

Getting 'Access denied' when calling REST service

I'm building a small app that consumes a REST service.
The REST service expects that the URL i interact with always have the API key as an URL parameter.
So no matter if i GET, POST, UPDATE or DELETE, my URL should always contain be something like this:
https://rest.service.tld:443/list?api_key=MY-KEY
https://rest.service.tld:443/lists/1/profiles/search?api_key=MY-KEY
I tried with the sample code from RestSharp webpage, but it get the statuscode Access Denied
Here's my code:
// Create client
var client = new RestClient( "https://rest.service.tld:443" );
client.Authenticator = new SimpleAuthenticator( "api_key", "MY-KEY", "", "" );
// GET list of items
var requestLists = new RestRequest( "lists", Method.GET );
IRestResponse<List<ListResponse>> listResponse = client.Execute<List<ListResponse>>( requestLists ); // Returns the correct list
// POST search
var requestProfiles = new RestRequest( "lists/1/profiles/search", Method.POST );
requestProfiles.AddParameter( "Criteria", "{\"email\":\my#email.tld\"}" );
IRestResponse profileResponse = client.Execute( requestProfiles ); // Returns 'Access Denied' status code
As far as i can tell, the POST method doesn't contain the correct querystring, instead my api_key is added as a parameter in the POST.
Is there a way to keep my API_KEY in the Querystring like i need it to be?
By default the api_key is added as a normal parameter, you need to explicitly enforce that you want the parameter to be embedded into the URL, by setting the ParameterType as follows:
var requestProfiles = new RestRequest( "lists/1/profiles/search{api_key}", Method.POST );
requestProfiles.AddParameter( "Criteria", "{\"email\":\my#email.tld\"}" );
requestProfiles.AddParameter( "api_key", MY-KEY, ParameterType.UrlSegment);
More info here