My question is how do I use laravel 4 with sentry 2 to authenticate users that is calling my API? What are the proper ways in doing this?
Example: a user in native iOS app calls my Laravel Web service (returns JSON response), how can laravel+sentry authenticate the user?
Thanks in advance and comment if you need more info.
Like mentioned by Antonio, if the client is able to persist cookies you should be set to go.
But,I will tell you my research on this topic. I looked for API Token Implementation with Laravel. One I could find was by Terry Appleby and his implementation is a composer package with name tappleby/laravel-auth-token. I implemented a much simpler version of the package using Sentry 2 at http://rjv.im/post/78940780589/api-token-authentication-with-laravel-and-sentry.
I called it a dirty one because I didn't consider much about security, expiration of tokens etc., but to answer your question, the above version does work and it is not secure unless you are in https environment.
To help you more I suggest github.com/kippt/api-documentation. It is the API Documentation for an app called kippt.com. I picked this one because it is really simple and could be a starting point if you are new to developing APIs. See how they support different kinds of authentication. To summarize on what Kippt supports: Browser Session (I am guessing iOS does support cookies), HTTP Basic Auth (Pass username and password every time in the header) and Token (Pass a token in header of every request). On Token implementation of Kippt, it just returns a token to the client after a successful authentication and one can save and use that token. That token never changes. In my blog post, I create a new token every time user logs in.
Hope I could help.
If the client is able to persist cookies, you just login with Sentry and it should work. Otherwise, after a common Sentry authentication, create and store an authentication token in your users table:
$table->string('api_token',96)->nullable();
Then use it in all other calls:
{
"token": "a358dafd256cb5b26a944eacc1c7428a97f6d1e079c3f1972696f1bea7fff099",
"user": {
"id": "3",
"email": "joe#doe.com",
"permissions": [],
"activated": true,
"activated_at": null,
"last_login": "2014-03-08 11:17:48",
"first_name": null,
"last_name": null,
"created_at": "2014-03-08 10:29:08",
"updated_at": "2014-03-08 11:17:48",
"api_token": "a358dafd256cb5b26a944eacc1c7428a97f6d1e079c3f1972696f1bea7fff099"
}
}
An article about this: http://rjv.im/post/78940780589/api-token-authentication-with-laravel-and-sentry
Related
I'm trying to complete a fairly simple process:
A web application, authenticated with Azure AD via a personal Microsoft account (i.e. an #hotmail account), makes a call to a second microservice.
The microservice is secured via a JWT, obtains a second token using the on-behlaf-of flow, and called the Microsoft Graph API to retrieve calendar events.
I can log into the web frontend OK, and call the second microservice OK. The second microservice can obtain an on-behalf-of (obo) token OK, but the problem I run into is that the obo access token provided to me fails to call the Graph API. The error I receive is this:
{"error":{"code":"NoPermissionsInAccessToken","message":"The token contains no permissions, or permissions can not be
understood.","innerError":{"oAuthEventOperationId":"7499efa7-932b-425d-8ad4-43206630f961","oAuthEventcV":"ed1BzGz2t/H/wK7JnZB6lQ.1.1.1","errorUrl":"https://aka.ms/autherrors#error-InvalidGrant","requestId":"3ca5fa79-423b-460e-9130-b7d1172ec841","date":"2021-09-13T09:24:17"}}}
My problem is similar to the one described here, where my obo JWT does not contains a roles claim. This is the decoded JWT sent to the Graph API:
{
"typ": "JWT",
"nonce": "A3IzBCOGrnE53ukPqb2jHjWYT0grwFbHo_OkzcUhSRc",
"alg": "RS256",
"x5t": "l3sQ-50cCH4xBVZLHTGwnSR7680",
"kid": "l3sQ-50cCH4xBVZLHTGwnSR7680"
}.{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/26375159-666a-4217-adfe-c06427b7798c/",
"iat": 1631522998,
"nbf": 1631522998,
"exp": 1631526898,
"acct": 1,
"acr": "1",
"aio": "AUQAu/8TAAAA1HEurZSE5YS0ADYs3oKeEEy6qhWwyXBZtoHtBPbIS/jo0OD5BTlQptuXZ3ZLtDczWZQw7b0+dUoCNdpN2mY4ew==",
"altsecid": "1:live.com:00014B90C0D373BC",
"amr": [
"pwd"
],
"app_displayname": "SpringBootMicroserviceDemo",
"appid": "5907efc0-f0b5-45db-b4cf-725f655009c3",
"appidacr": "1",
"email": "matthewcasperson#hotmail.com",
"family_name": "Casperson",
"given_name": "Matthew",
"idp": "live.com",
"idtyp": "user",
"ipaddr": "45.132.224.55",
"name": "matthewcasperson",
"oid": "e377a23b-1b88-4d14-9c99-fc6ecd4a41c7",
"platf": "3",
"puid": "1003200180F4FB20",
"rh": "0.AVAAWVE3JmpmF0Kt_sBkJ7d5jMDvB1m18NtFtM9yX2VQCcNQAKM.",
"scp": "Calendars.Read openid profile User.Read email",
"signin_state": [
"kmsi"
],
"sub": "vhbBIoJqEHoEaJLMVsG5sh0C4FjoJiAfAKOFCzrC8hQ",
"tenant_region_scope": "NA",
"tid": "26375159-666a-4217-adfe-c06427b7798c",
"unique_name": "live.com#matthewcasperson#hotmail.com",
"uti": "ufe_nSFv_UuiYCOur72mAQ",
"ver": "1.0",
"wids": [
"13bd1c72-6f4a-4dcf-985f-18d3b80f208a"
],
"xms_st": {
"sub": "PCUskXV6aCsNgHz9Yug42-WhS-iea1gy5GI5trkTZ4E"
},
"xms_tcdt": 1631479794
}.[Signature]
The JWT has Calendars.Read in the scp, but no roles, which appears to be an issue.
The JWT above will complete a call to the "me" endpoint OK (i.e. https://graph.microsoft.com/v1.0/me). Unfortunately, calling the "me" endpoint is as far as any example provided by Microsoft goes.
The sample application here provides a controller that shows calling the "me" endpoint on the Graph API, and if I modify the Graph API client to include the https://graph.microsoft.com/Calendars.Read scope, it also fails the Graph API request.
The sample application here appears to be a slightly older example in that it builds the token manually rather than injecting something like #RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient client (which is described in more detail on the Spring blog here). But again the sample only goes so far as to call the "me" endpoint.
As far as I'm aware I have enabled all the correct settings. My Azure AD Application has requested Calendars.Read both as a delegated and application permission, and the permissions have been granted consent:
My web based application can be found here, and the Calendar API microservice can be found here.
Further reading:
Azure AD v2 roles not included in Access Token: This described how to add custom roles to the JWT, but I did not see how it could be used to add Graph API roles.
Graph API access token for calendar read reports No Permissions: This talked about adding application permissions, which did not resolve the issue for me.
Microsoft Graph API outlook task folder : NoPermissionsInAccessToken: This issue talks about different OAuth flows, but this doesn't appear to apply to a resource server that accepts a JWT.
How to solve "NoPermissionsInAccessToken" returned by Microsoft Graph when reading calendar or sending mail: The answer here talks about "Adding guest users is meaningless", which makes no sense to me.
Spring Boot Starter for Azure Active Directory developer's guide: This is a reasonably detailed tutorial that even speaks about resource servers, but I could not find any tips that addressed the NoPermissionsInAccessToken error.
OAuth 2.0 Sample for Azure AD Spring Boot Starter client library for Java - This is another reasonably detailed tutorial that talks about accessing a second resource server, but again I didn't find any clues to the NoPermissionsInAccessToken error.
List events and Get calendar: This indicates that a Delegated (personal Microsoft account) can use the Calendars.Read permission.
The crux of my issue is that using the on-behalf-of flow appears to be the recommended solution for calling the Graph API from a resource server that accepts a JWT from a front end application. Defining the delegated permissions in the Azure AD Application, consenting to them, defining them in an authorization-clients: in the application.yaml file, and getting a client via #RegisteredOAuth2AuthorizedClient("graph") OAuth2AuthorizedClient client are the only consistent instructions from the Microsoft documentation and sample applications. And yet the resulting JWT can only call the "me" endpoint.
Can anyone shed some light on how to call the Graph API with on-behalf-of token in Spring boot?
Somebody has created a system which use Google API. It happens that I have been using this system for several months to upload files to G Drive and it worked very well.
However today I realized in the following string that there was an expiry date (not updated until today) which prevent from uploading files. My understanding is that a token is generated every time my code is requesting API access, but this shows the same access_token and refresh token with expiry date. I tried to read official doc without clear understanding. Can you explain simply what I should think about it and hint at how I should re generate the needed token please.
{"access_token": "xxx", "client_id": "yyy", "client_secret": "nnn", "refresh_token": "bbb", "token_expiry": "2021-02-24T05:33:24Z", "token_uri": "https://accounts.google.com/o/oauth2/token", "user_agent": null, "revoke_uri": "https://oauth2.googleapis.com/revoke", "id_token": null, "id_token_jwt": null, "token_response": {"access_token": "xxx", "expires_in": 3599, "scope": "https://www.googleapis.com/auth/drive", "token_type": "Bearer"}, "scopes": ["https://www.googleapis.com/auth/drive"], "token_info_uri": "https://oauth2.googleapis.com/tokeninfo", "invalid": true, "_class": "OAuth2Credentials", "_module": "oauth2client.client"}
How much i understood it is that as we need multiple parameters to access a Google API which include authentication etc. As there are multiple steps to validate an API call, if they succeed, we are provided with an access_token which now represents that all the processes (or authentication etc) was successfull and now the access_token is a proof for that. So after that, only the token will be checked (until its expiry date) and the process will repeat after the expiration.
The authorization sequence begins when your application redirects a browser to a Google URL; the URL includes query parameters that indicate the type of access being requested. Google handles the user authentication, session selection, and user consent. The result is an authorization code, which the application can exchange for an access token and a refresh token.
The application should store the refresh token for future use and use the access token to access a Google API. Once the access token expires, the application uses the refresh token to obtain a new one.
More details Here
I have a SPA website built over Laravel and Vue.
I am using axios to get the responses and all working fine.
The most of the data is vendor, categories and products and nothing sensitive in it however products has some data which I need to use in frontend however I don't want my competitors to get hold on to that data.
How to do I go about that? so I get the data but it's hidden as well?
So I thought may be I encrypt it and then decrypt it but not sure if that's the right approach
{
"Products": [
{
"ID": 9950,
"VID": 114,
"Name": "TBH Special Burger ",
"Category": 224,
"Description": "",
"Image": "",
"Price": "250",
"DisplayPrice": 0,
"DealPrice": 0,
"Percentage": "15",
"Cust_Percentage": "0.00",
"DateTime": "2018-10-08 19:03:40",
},
],
}
In above response only percentage related data is I am trying to secure.
You are looking for Laravel Passport.
Laravel makes API authentication a breeze using Laravel Passport, which provides a full OAuth2 server implementation for your Laravel application in a matter of minutes.
With Passport, only authenticated users can access your data via API.
Read the documentation in the link above and give it a try.
If non authenticated users access your api by typing the url in his browser, this is the response that he will get:
{
"message": "Unauthenticated"
}
Consuming Your API With JavaScript
Laravel provides a middleware that allow you to consume your api from your JS app. From the docs:
Typically, if you want to consume your API from your JavaScript application, you would need to manually send an access token to the application and pass it with each request to your application. However, Passport includes a middleware that can handle this for you. All you need to do is add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
Hope it helps.
You can use API Resources to specify witch fields you would like to show in response
take look to docs:
https://laravel.com/docs/5.8/eloquent-resources
I am building a REST API, no views, just routing for a front written in Angular.
For auth purposes, I need to create tokens, send them in the payload and verify them.
My question is why do I need to have 5 tables for this, would it be possible to store the secret on the ENV and just operate without calling the DB each time? I've been googling for answers on this without avail, hope to get clarity here. Thanks.
You require these tables. oauth_clients table stores your client_id and client_secret.
There are different type of clients available, in your case its better to use password client (where password_client set to 1 in auth_clients table).
{
"username": "your-laravel-username",
"password": "your-laravel-password",
"client_id": id-from-oauth-clients-table,
"client_secret": secret-from-oauth-cleints-table,
"grant_type": "password", //this is to use password client, search for password_client - 1 in oauth_client table
"scope": "conference"
}
This client_id and client_secret you can use in the login request to get the bearer token. This bearer token you can use to get the access to all the apis.
Once you have the bearer token ready you can use it for further request, now need to use the login api for each request.
I have the following setup:
IdenetityServer3 for auth (OAUth / OpenID)
ASP.NET WebApi back end
Ember-cli UI
I have the auth flow working nicely - I haven't managed to get the admin UI working yet but I can prepopulate users, scopes and clients so that's fine.
When the user auths against IdentityServer3 they are redirected back to the UI and the UI uses the oidc-client to retrieve the users info from the JWT - the client also uses the bearer token to send to the API to auth requests - all good.
My problem is that the IddentityServer is in charge of authentication / authorization - but the API doesn't yet have any notion of a user - but it needs that.
What is the best way of syncing user info between IdentityServer and my API? How can I best manage things like roles and user hierarchy? Is there a way for the API to query IdentityServer for this? It seems silly holding a copy of the user info locally to the API when we have an identity server that manages all of this.
IdentityServer exposes a UserInfo endpoint (https://identityserver.github.io/Documentation/docsv2/endpoints/userinfo.html) which you can call to retrieve additional information about a user.
However, wherever possible, try to achieve what you need to by passing a token that has the relevant amount of claims so that you can make AuthZ decisions without requiring a call to Identity Server. This reduces coupling, and means you have less outbound calls from your API.
E.g. When you sign in, a JWT token could be created that contains the roles the user is a member of plus the users unique id (sub claim)
{
"iss": "https://my.api.com/trust",
"aud": "https://my.api.com",
"exp": 1512748805,
"nbf": 1481212805,
"scope": "openid",
"sub": "83b0451a718b4d54b930d6fe9cb7b442",
"idp": "site",
"roles": [
"role1",
"role2"
]
}
Your API can now just check the claims presented to it and say 'To call this API endpoint, the token presented to me must have role2 in the roles claim'.
You can also do this with the scopes, using the scope attribute
A well designed JWT token will contain the right amount of information to make AuthZ decisions without requiring lots of additional calls, whilst keeping the overall size of the token as small as possible - remember, it's included on every request.