How to manage CRSV token manually in Symfony? - security

I'm trying to use the CRSF token management without a FormType. So in a twig template i just use that to generate a token:
{{ csrf_token( inception_inscription ) }}
In the controller i'm trying this :
$tokenManager = $this->get('security.csrf.token_manager');
$token = $request->get('token');
inception = $this->container->getParameter('crsf_inscription_inception');
if (!$tokenManager->isTokenValid($tokenManager->getToken($inception, $token))) {
throw new HttpException(400, 'Invalid token');
}
But in fact the method isTokenValid always return true. I can force the $token vaiable to what i want, it's never false, so the validation is useless.
When i do debug step by step, i walk throught a Symfony\Component\Security\Csrf::getToken() and that method is testing that : ($this->storage->hasToken($tokenId)) whic always return false and force the process to generate a new Token.
I don't really undertand how it works.
Here is ore information about my code :
Symfony 2.6.x
framework:
secret: "%secret%"
router:
resource: "%kernel.root_dir%/config/routing.yml"
strict_requirements: ~
form:
csrf_protection:
enabled: true
field_name: token_my
csrf_protection:
enabled: true
validation: { enable_annotations: true }
templating:
engines: ['twig']
#assets_version: SomeVersionScheme
default_locale: "%locale%"
trusted_hosts: ~
trusted_proxies: ~
session:
handler_id: ~
name: 'my'
fragments: ~
http_method_override: true
# Twig Configuration
twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
inception_inscription: %crsf_inscription_inception%

From what I understand, $tokenManager->getToken($tokenId) always generates a new, valid token. You would probably check the provided token instead, e.g.:
$tokenManager = $this->get('security.csrf.token_manager');
$tokenId = $this->container->getParameter('crsf_inscription_inception');
$tokenValue = $request->get('token');
$token = new CsrfToken($tokenId, $tokenValue);
if (!$tokenManager->isTokenValid($token)) {
throw new HttpException(400, 'Invalid token');
}

Related

I'm trying to use a custom cookie service for my Node oidc authentication, but I don't know how to instantiate it with the needed parameters

This is a Node app with OIDC login. I want to store the JWT in the cookie.
I'm using version 12 of the library 'angular-auth-oidc-client'. I can't use a later version of this library.
The documentation says to set up your app.module.ts like this:
imports: [
/*...*/,
AuthModule.forRoot({
config: {
authority: ...,
redirectUrl: ...,
/*...*/,
storage: new MyCustomStorage()
}
})
So it uses that 'storage' parameter.
This works correctly if I use, for instance, localStorage in my new MyCustomStorage. But I want to use the cookie.
So, if I for instance make my MyCustomStorage like this:
import { CookieService } from 'ngx-cookie-service';
#Injectable({
providedIn: 'root',
})
export class MyCustomStorage implements AbstractSecurityStorage {
constructor(private cookieService: CookieService) {
}
remove(key: string): void {
throw new Error('Method not implemented.');
}
clear(): void {
throw new Error('Method not implemented.');
}
read(key: string) {
let item = this.cookieService.get(key);
if (!!item) {
return JSON.parse(item);
}
else {
return null;
}
}
write(key: string, value: any) {
value = value || null;
//Expiration time can be set in the third parameter of below function.
this.cookieService.set(`${key}`, JSON.stringify(value), undefined, undefined, undefined, true, 'Strict');
return true;
}
}
I believe this would work... however I now get an error in my app.module.ts, because now creating a new MyCustomStorage() requires a CookieService parameter to be injected.
But that CookieService is automatically injected into the MyCustomStorage usually...
Do I need to manually instantiate a new CookieService in the "storage: new MyCustomStorage()" line? If so, it asks for parameters for DOCUMENT and PLATFORM_ID and REQUEST. Do I have to instantiate those as well? If yes... how do I create a new document and platform id for this new CookieService()?

terraform code to append existing key value pair

I'd like to append a new key-value pair to an existing yaml-based structure by using terraform.
For example I have the following yaml file:
urls:
- id: site1
url: google.de
- id: site2
url: bing.com
- id: site3
url: duckduckgo.com
Now I want to add a key-value pair based on some conditions.
(It's not required to write to the file. The list will be used in a loop later on)
Expected:
urls:
- id: site1
url: google.de
secure: false
- id: site2
url: bing.com
secure: false
- id: site3
url: duckduckgo.com
secure: true
What I already tried:
locals {
x = tomap({
for k in keys(yamldecode(file("urls.yaml"))):
k => merge(
yamldecode(file("urls.yaml"))[k],
{ urls = { url = merge(yamldecode(file("urls.yaml"))[k].urls[0], { secure = false }) }}
)
})
}
Works for the first url but I wasn't able to loop over the urls to get an index.
Second approach:
locals {
x = tomap({
for k in keys(yamldecode(file("urls.yaml"))):
k => {
for l in keys(yamldecode(file("urls.yaml"))[k]):
l => l == "urls" ? <tbd> : yamldecode(file("urls.yaml"))[k][l]
}
})
}
But I wasn't able to merge or replace the structure at <tbd> if the key matches.
It always fails because of mismatches:
arguments must be maps or objects, got "tuple".
Any idea?
After a yamldecode function converts from YAMl formatted string to HCL2, the resulting type would be map(list(object)); for example:
{ "urls" = [{id="site1", url="google.de"}] }
That makes it a bit more clear how to add a key-value pair to the nested object with a for expression. We need to preserve the structure, keys, and values of the original, and add a single key value pair in the nested object.
# map constructor and iterate through yaml map
# key = "urls", urls is list of objects
{ for key, urls in yamldecode(file("urls.yaml")) : key => [
# inside list constructor now
# url_attrs is single object in list of objects
for url_attrs in urls : {
# inside object constructor now
# retain same key value pairs, and add a "secure" key value pair
id = url_attrs.id
url = url_attrs.url
secure = false
}
]
}
In HCL2 this results in (according to local testing)
{
urls = [
{
id = "site1"
secure = false
url = "google.de"
},
]
}
which is equivalent to:
urls:
- id: site1
url: google.de
secure: false
I notice the logic for the secure boolean is a placeholder and the example code always assigned false, so I have done the same above.

Change authorized user in tests

I want to test access to a method for a group of users with different roles in one test. I am trying to change the logged in user like this:
#Test
void allMenusAuthorizePermissions() throws Exception {
for (User user : ALL_ROLES_USERS) {
Authentication authentication = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
SecurityContextHolder.clearContext();
SecurityContextHolder.getContext().setAuthentication(authentication);
log.debug("User role: " + user.getAuthorities());
if (user == ADMIN || user == EDITOR) {
perform(get(MenuEditorController.MENU_EDITOR_URL).principal(authentication))
.andExpect(status().isOk());
}else{
perform(get(MenuEditorController.MENU_EDITOR_URL).principal(authentication))
.andExpect(status().isForbidden());
}
}
}
But no matter how hard I try, perform(get (...)) is always performed from the first user from the ALL_ROLES_USERS array. This can be seen from the log:
o.s.s.a.i.a.MethodSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken#e74255f0: Principal: +79990200001; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: CLIENT
-the same user in every iteration!
Any idea why this might be happening? Maybe perform(get(...)) is passing the JSESSIONID of the first user? I don't know where to dig anymore
You need to use:
#Test
void allMenusAuthorizePermissions() throws Exception {
for (User user : ALL_ROLES_USERS) {
log.debug("User role: " + user.getAuthorities());
if (user == ADMIN || user == EDITOR) {
// perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user.getUsername()).authorities(user.getAuthorities())))
perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(status().isOk());
}else{
perform(get(MenuEditorController.MENU_EDITOR_URL).with(SecurityMockMvcRequestPostProcessors.user(user)))
.andExpect(status().isForbidden());
}
}
}
How to Mock the security context in Spring MVC for testing

Controller returning login form while returning file with Symfony 5

I have a security problem using Symfony5.
I have configured security.yml:
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: ROLE_USER }
Everything works fine, except when I try to load a file (PDF), even if the route is allowed. The pdf shows the login form, but I'm already logged.
I feel it's because I return a File object in my controller:
public function viewpdf($id, \Knp\Snappy\Pdf $snappy) {
// some code
// load the file from the filesystem
$file = new File($path_file);
// display the file contents in the browser instead of downloading it
return $this->file($file, $file_name, ResponseHeaderBag::DISPOSITION_INLINE);
}
Same problem with another controller when I want to force download:
return new PdfResponse(
$snappy->getOutput($pageUrl),
$file_name
);
How can I view and download my pdf while I'm already logged in?
Thank you,
OK, I found the solution to this problem, for both cases:
// Inside controller
// KNP bbundle does not have the login/session data
$session = $this->get('session');
$session->save();
session_write_close();
$PHPSESSID =$this->get('session')->getId();
$output = $snappy->getOutput($pageUrl, array(
'cookie' => array(
'PHPSESSID' => $PHPSESSID
)));
if($download == 1) {
return new PdfResponse($output, $file_name);
} else {
return new Response(
$output, 200,
array(
'Content-Type' => 'application/pdf',
'Content-Disposition' => sprintf('filename="%s"', $file_name)
)
);
}

Basic authentication for Swagger-UI not working correctly

I have setup Swagger within my ASP.NET project using NSwag which works fine but I am attempting to add support for authentication.
My authentication model is a simple username/password that uses OAuth using ApplicationOAuthProvider
The URL I use to login is as below
/token
With the POST parameters:
grant_type=password&username=${username}&password=${password}
Now my swagger setup [in Global.asax] is
app.UseSwaggerUi(typeof(Global).Assembly, new SwaggerUiSettings
{
MiddlewareBasePath = "/swagger",
OAuth2Client = new OAuth2ClientSettings
{
ClientId = "my_auth_id",
//ClientSecret = "bar",
AppName = "my",
//Realm = "my_realm",
//AdditionalQueryStringParameters = { { "foo", "bar" } }
},
DocumentProcessors = {
new SecurityDefinitionAppender("oauth2", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.Basic,
Description = "Description is set htere",
Flow = SwaggerOAuth2Flow.Password,
AuthorizationUrl = "https://localhost:28866/token?",
TokenUrl = "https://localhost:28866/token",
In = SwaggerSecurityApiKeyLocation.Query
//Scopes = new Dictionary<string,string>
//{
// //{ "read", "Read access to protected resources" },
// { "write", "Write access to protected resources" }
//}
})
},
OperationProcessors =
{
new OperationSecurityScopeProcessor("oauth2")
}
});
I know its a bit messy but I was literally trying every option I could to make it work.
So this actually gives me the Authorize button and a Username and Password field. But when I click login it refreshes the swagger.json but doesnt actually attempt to log in anywhere?

Resources