PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label bearer-token. Show all posts
Showing posts with label bearer-token. Show all posts

Sunday, September 4, 2022

[FIXED] How can I download a file from frontend with Authorization Header

 September 04, 2022     authentication, bearer-token, cookies, download, express     No comments   

Issue

Here is my backend code. It has 2 protected routes. Authorization Header is needed (Bearer token).

  • These routes allows you to download your photo and your cv.

I have no issue with my backend. It is working with postman and mobile applications. I think there is a limitation for frontend.

I do NOT want

  • I don't want to use fetch to download these files as blob. Because it doesn't allow to browser to show its progress bar.
  • I don't want to change my authentication method from Bearer token to cookie. I can already do this with cookie.

I wonder why Bearer token is more popular than cookie If I have to use cookie to make this happen.

Backend

// other imports .....
const path = require('path');
const fs = require('fs');
const express = require('express');
const app = express();

app.use((req, res, next) => {
  try {
    const token = req.get('Authorization');
    if(!token) {
      throw new Error('401');
    }
    const userId = getIdFromToken(token);
    if(!userId) {
      throw new Error('401');
    }
    res.locals.userId = userId;
    next();
  } catch (error) {
    next(error);
  }
})
app.get('/api/me/photo', (req, res) => {
  const userId = res.locals.userId;
  
  const imagePath = path.resolve(process.env.DISC_PATH, 'images', `${userId}.png`);
  res.attachment('me.png');
  res.set('Content-Type', 'image/png');
  const stream = fs.createReadStream(imagePath);
  res.pipe(stream);
})

app.get('/api/me/cv', (req, res) => {
  const userId = res.locals.userId;
  
  const pdfPath = path.resolve(process.env.DISC_PATH, 'cv', `${userId}.png`);
  res.attachment('my-cv.pdf');
  res.set('Content-Type', 'application/pdf');
  const stream = fs.createReadStream(pdfPath);
  res.pipe(stream);
})

...

// error handling, etc...

Frontend


<html>
<body>

<!-- How can I send the Authorization header here -->
<img src="/api/me/photo" />

<!-- How can I send the Authorization header here -->
<a href="/api/me/cv">Download My CV</a>

<!-- How can I send the Authorization header here -->
<button id="btn"> Download My CV (V2) </button>

<script>
  const btn = document.getElementById('btn');
  btn.addEventListener('click', () => {
    // How can I send the Authorization header here
    window.open('/api/me/cv');
  });
</script>

</body>
</html>


Solution

I wonder why Bearer token is more popular than cookie If I have to use cookie to make this happen.

One advantage of an Authorization: Bearer header over cookie-based authentication is precisely that the browser does not automatically include the header in a request to the given URL. So you cannot be tricked into clicking on a link that would trigger an authenticated request that you did not intend.

In other words: With Authorization: Bearer as authentication mechanism you are safe from "cross-site request forgery" (CSRF) attacks.

Backends that use cookie-based authentication have to implement extra countermeasures against CSRF.

For your problem, this means that the two don't go together. If you want the convenience of a "normal" browser request (with its progress bar), you expose the user to CSRF, unless you take said countermeasures. (This may not be a serious threat if the request only downloads something. But an attacker could at least measure the running time of the CV download request and deduce something from that.)

Possible workaround:

Implement an API (authenticated with Authorization: Bearer header) that generates a download URL which includes a short-lived token, and have the browser download the desired document with a normal request to that URL. The second request is technically unauthenticated, but the token makes the URL unguessable.

If the token is a JWT, you need not even store it on your server but can simply write the username and expiry time in it and sign it with the server's private key. If you prefer you can also put the token in a cookie rather than in the URL.



Answered By - Heiko Theißen
Answer Checked By - David Marino (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

[FIXED] How to add an additional check to JWT token lifetime validation?

 September 04, 2022     asp.net-core, authentication, bearer-token, jwt     No comments   

Issue

In my web application I want to perform all the default lifetime checks (not before, expires, ...), plus perform one additional check (lifetime < 2 hours).

First I tried this:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o => {
        o.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateLifetime = true,
            LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => {
                // --> my custom check <--
            }
        };
    });

This will perform my custom check, but it will skip the default implementation, so all the regular checks (not before, expires, ...) are no longer performed.

Then I call the default implementation from within my handler, like this:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o => {
        o.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateLifetime = true,
            LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => {
                    Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(notBefore, expires, securityToken, validationParameters);
                // --> my custom check <--
            }
        };
    });

But this will recursively call my handler and eventually crash my application.

So... what's the correct way to extend the default lifetime validator?


Solution

You can do this:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, o => {
        o.TokenValidationParameters = new TokenValidationParameters()
        {
            ValidateLifetime = true,
            LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => {
                var clonedParameters = validationParameters.Clone();
                clonedParameters.LifetimeValidator = null;
                bool valid = Microsoft.IdentityModel.Tokens.Validators.ValidateLifetime(notBefore, expires, securityToken, clonedParameters);
                // --> my custom check <--
            }
        };
    });

So we copy the TokenValidationParameters and set the lifetime validator reference to null so it prevents the recursive call and doesn't modify the actual instance where you registered the validator.



Answered By - juunas
Answer Checked By - Pedro (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Monday, February 28, 2022

[FIXED] Laravel 8 bearer token exception handling if bearer token not found

 February 28, 2022     api, bearer-token, laravel, php     No comments   

Issue

Hello I can't understand how to set error message when user put some wrong bearer token currently I am not getting any exceptional error message if I try wrong bearer token in postman.

public function general_information(Request $request) {
    try {
        return $token = $request->bearerToken();
    } catch(Exception $e) {
        return $e->message();
    }
}

Solution

in app/Exceptions/Handler.php add this function and change the message as you want

protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['error' => 'haha'], 401);
    }

    return redirect()->guest('login');
}

here return haha message

note define this before write the function
Illuminate\Auth\AuthenticationException;



Answered By - Ossama Abd
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing