Laravel API. How to check permissions

In your Laravel app build you have:

Route::get('/private-scoped', function (Request $request) {
    return response()->json([
        "message" => "Hello from a private endpoint! You need to have a valid access token and a scope of read:messages to see this."
    ]);
})->middleware('check.scope:read:messages');

Every time I make API request like said in your docs, I get “Insufficient scope” answer. In seems that docs are old and when said ‘scope’ it means ‘permissions’, I’ve added permissions to my access token. I have field ‘permissions’ in it. Do I need to change code of CheckScope Laravel middleware or something else? How to check permissions in Laravel api requests?

It seems that the access token you’re using was not issued to read:messages. When you did the authorize request (might be via login wrapper method in the Laravel example) to request the access token, did you ask for the read:messages scope in it?

I am referring to the scopes you use like in this example:

Make sure that in your Auth0 Dashboard, the API containes the scopes/permissions read:messages (you can use these terms interchangeably, but it refers to the scope claim in the access token in the end) and that your client application is requesting this scope in the authorize request (for which in the example the login wrapper method is used.)

Also, make sure that you set the correct audience parameter in the request, which should be your API identifier (which you set in the Auth0 dashboard for your API).

When you look into the decoded access token, which scopes and audience does it show? Best if you could post both the scope, audience that are in the access token, as well as the way you request the access token in the first place.

1 Like

In frontend I use React.

My settings are:

  1. Permissions of Admin role

  1. User who has Admin role

  1. Permissions of the user

  1. API settings

In React in main component (the whole app is protected) I have:

import { renewSession } from 'components/Auth';
componentDidMount() {
    // Check session on server, if there is no active session then redirect to login page
    // Code is from your 05-Token-Renewal
    renewSession(this.props.dispatch);
}

Auth.js:

const _auth0connection = new auth0.WebAuth({
    domain: AUTH_CONFIG.domain,
    clientID: AUTH_CONFIG.clientID,
    redirectUri: AUTH_CONFIG.callbackUrl,
    responseType: 'token id_token',
    audience: `audience id`,
    scope: 'permissions role openid profile'
});
renewSession(){
    _auth0connection.checkSession({}, (err, authResult) => {

        if (authResult && authResult.accessToken && authResult.idToken) {
           _setSession(authResult, dispatch);
        } else if (err) {
            console.log(err, "error" );
            login(); // which is _auth0connection.authorize()
        }

    });
}
const _setSession = (authResult) => {
    const authInfo = {
        clientId: authResult.idTokenPayload.sub,
        expiresAt: authResult.expiresAt,
        accessToken: authResult.accessToken,
        state: authResult.state,
        idTokenPayload: {
            issuedAt: authResult.idTokenPayload.iat,
            expireAt: authResult.idTokenPayload.exp,
            updatedAt: authResult.idTokenPayload.updatedAt,
            name: authResult.idTokenPayload.name,
            nickname: authResult.idTokenPayload.nickname,
            picture: authResult.idTokenPayload.picture,
        },
        permissions: jwt_decode(authResult.accessToken).permissions
    };
    // Set timer to redux store which call renewSession again after calculated time passed
   // ((authResult.expiresIn * 1000) + new Date().getTime())
    _scheduleRenewal();
    // Dispatch action, set data to redux store
    dispatch(setAuthStore(authInfo));
}

After that, I have access token in store.auth.user.accessToken.

Then I copy access token from redux store and using postman send my request to my backend api made with Laravel (I’ve downloaded configured sample from here - Auth0 Laravel API SDK Quickstarts: Authorization).

My route in Laravel api.php:

Route::get('/test', function (Request $request) {
    return response()->json([
        "message" => "Its working. Laravel."
    ]);
})->middleware('check.scope:test:test');

As I understand, when I make a request in postman, Laravel should check recieved access token on auth0 server, and if user has permission ‘test:test’ it should accept request and give out “Its working. Laravel.”

But something is not working… Or it’s just me didn’t understand something.

Use this in your Auth.js instead:

scope: 'permissions role openid profile test:test settings:read read:messages'

By the way: You can use https://jwt.io to decode and check the payload of an access token, where it also shows you the scopes that this token is valid for. You would see that it doesn’t contain test:test.

1 Like

5

Even with the code I’ve listed above I have permissions of user in access token.
Honestly speaking, I did not understand why I should add permissions to scope as you said:

scope: ‘permissions role openid profile test:test settings:read read:messages’

I would like to have automatic checking permissions without hardcoding it in scope. Is it possible?
Permissions may change, they may be deleted, edited, I can add new. Access token will always contain all user permissions and in React I just need to check on Component level if user allowed to visit it or not. It would be great if it would be possible to have this job done in Laravel automatically too. Laravel gets all permission of user in access token, checks for every specific protected route (permission part - ->middleware('check.scope:->>**test:test**<<-')) if it is present in user permissions and give out positive respond.

I see your point. I meant it as a workaround if you wanted to keep using the middleware that only validates the scope claim, but I saw that you meanwhile adjusted your own middleware to check the permissions.

@alt1 The reason why permissions aren’t returned in the scope claim if you don’t explicitly request the scopes, is laid out here: