Client credentials grant generate tokens for lifetime - oauth-2.0

I am creating an API in laravel a using two grants [password, client_credentials] and I want to configure token lifetime for separate for both grants.
If I configure token lifetimes according to laravel passport documentation then its set's for both grants.
I need help to configure separate lifetime for both grants.

Create the access token with $token = $user->createToken('API Access') and use a query with DB::table('oauth_access_tokens')->where('id', $token->id)->update([...]) to change the value of 'expires_at' manually.
Apply same on 'oauth_refresh_tokens' with ->where('access_token_id', $token->id)

In the boot function of your AuthServiceProvider you can still check the value of grant_type in your request to define different lifetime.
if($request["grant_type"] === "client_credentials"){
// If token is a client_credential we define it to one year
Passport::tokensExpireIn(Carbon::now()->addYear());
}else{
// Or we define it to only one hour
Passport::tokensExpireIn(Carbon::now()->addHour());
}

Related

How to get a forever token using Oauth1?

I sell products online through a website I wrote. To manage my fulfilment flow, when a purchase is made I want my app to automatically create a card on a Trello board.
I've managed to do everything okay except that after a few minutes the token that I was using expires, even though I thought I had created a token that would never expire.
I can't manually authenticate every time an order comes in.
Here's the code I've written to generate tokens. (Oauth1).
Step 1 (one time): Get a manually authorized resource owner key, resource owner secret, and verifier.
import requests
from requests_oauthlib import OAuth1Session
oauth = OAuth1Session(CLIENT_KEY, client_secret=CLIENT_SECRET)
fetch_response = oauth.fetch_request_token(REQUEST_TOKEN_URL)
resource_owner_key = fetch_response.get('oauth_token')
resource_owner_secret = fetch_response.get('oauth_token_secret')
print(f'resource_owner_key: {resource_owner_key}')
print(f'resource_owner_secret: {resource_owner_secret}')
auth_url = oauth.authorization_url(AUTHORIZE_TOKEN_URL, scope='read,write', expiration='never') # expiration never
print(auth_url)
# Now manually authenticate in browser using this URL. Record resource owner key, secret and verifier
Step 2 (every time): Use resource owner key, resource owner secret, and verifier to generate a token.
oauth = OAuth1Session(CLIENT_KEY,
client_secret=CLIENT_SECRET,
resource_owner_key=RESOURCE_OWNER_KEY,
resource_owner_secret=RESOURCE_OWNER_SECRET,
verifier=VERIFIER)
oauth_tokens = oauth.fetch_access_token(ACCESS_TOKEN_URL)
token = oauth_tokens.get('oauth_token')
Step 3: Use token in POST request to make card.
This all works fine for a few minutes, then on trying to use it again I get the error:
requests_oauthlib.oauth1_session.TokenRequestDenied: Token request failed with code 500, response was 'token not found'.
I thought that token was last forever? I can still see under my account details on Trello:
read and write access on all your boards
read and write access on all your teams
Approved: today at 6:30 AM
Never Expires
Set expiration long expiration time in token like expire in 2099 something like that
Solved - I was doing everything right, just that Step 2 should only be done once instead of every time. I thought I had to generate a new token for each new request, but the token generated at the 'token = ' line is actually good to save off and use forever.

Identity Server 4 Authorization Code Flow with Client Credentials (allowing one client instance deny another)

What I got so far:
In a project I have an authorization server (Identity Server 4), some (let's say two) protected APIs (Api Resource) and some trusted clients (automated, no user interaction) which should access the Identity Server via the backchannel (right?). Imagine the client is a Amazon Fire TV box kind thingy.
According to what I have read so far over the last weeks a suitable flow for this scenario is the OpenID Connect Authorization Code Flow.
clients are trusted (and can maintain a secret)
Authorization Code flow supports refresh tokens (which I want to use)
the client is actually not the resource owner but requires access to the full api resource
What I have in my (theoretical) structure:
I have two API Resources (one resource for each API version)
api.v1
api.v2
I also have two series of my API clients
client.v1 supports only api v1 & should only have access to api.v1 resource
client.v2 supports api v1 & v2 and therefore should have access to both api resources
Identity Server 4 StartUp.cs configuration (so far)
public void ConfigureServices(IServiceCollection services)
{
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources
(
new List<ApiResource>
{
new ApiResource("api.v1", "API v1"),
new ApiResource("api.v2", "API v2")
}
)
.AddInMemoryClients
(
new List<Client>
{
new Client
{
ClientId = "client.v1",
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
AllowAccessTokensViaBrowser = false,
ClientSecrets = { new Secret("secret1".Sha256()) },
AllowedScopes = { "api.v1" }
},
new Client
{
ClientId = "client.v2",
AllowedGrantTypes = GrantTypes.CodeAndClientCredentials,
AllowAccessTokensViaBrowser = false,
ClientSecrets = { new Secret("secret2".Sha256()) },
AllowedScopes = { "api.v1", "api.v2" }
}
}
);
}
The theory what I am struggling with is the authorization code part.
I want to have each client instance (again imagine it as a small box) a different authorization code allowing one instance access but deny fo another one.
Is the authorization code intended to be used for that?
And one important thing I haven't understood in all the time: CodeAndClientCredentials defines two grant types. Does this mean connecting with that requires both (code AND client credentials) or is it an one of them definition (code OR client credentials).
The Identity Server 4 code I am struggling with is:
In the code defining the client I can only find AuthorizationCodeLifetime but no field to set the authorization code itself.
It seems I can define a list of client secrets.
ClientSecrets = { new Secret("secret1".Sha256()) },
Does this mean one client Id can have multiple secrets used? Are different client secrets better suitable for my "allow one deny the other" problem?
Edit
Ok, I have re-read that and now I got it (at least a bit more): the authorization code is not defined sent by the client but the client receives it.
The authorization code flow returns an authorization code (like it says on the tin) that can then be exchanged for an identity token and/or access token. This requires client authentication using a client id and secret to retrieve the tokens from the back end
from this blog here
But how would I have to configure my Identity Server to allow one instance and deny another.
By using different client secrets? Using extension grants?

How do you use an iOS Google ID Token to fetch a user's full profile from the backend (Node JS)?

I'm using the Google Login iOS SDK to login, then passing GIDGoogleUser.authentication.idToken to the server, which I'm then verifying in Node JS. The verification in the code below works fine. "payload" var ends up being correct with basic information about the user.
How do I translate the idToken into credentials that I can use to git the people.get endpoint? (I want to know whether the user is using the default Google profile photo or not, and that is available from the people.get endpoint.) This does not seem to be documented anywhere.
https://developers.google.com/people/api/rest/v1/people/get
var auth = new GoogleAuth;
var client = new auth.OAuth2(GoogleUtils.clientIDs, '', '');
client.verifyIdToken(
token,
GoogleUtils.clientIDs,
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3],
function(e, login) {
if (e) {
return next(e, null);
}
var payload = login.getPayload();
return next(null, payload);
});
Thanks for your help. I can't seem to find any of this info in the documentation. Google's APIs are very poorly documented it seems.
Unfortunately, as noted, the current ID token payload does not say whether the photo is the default one (probably something we should add). If you need an access token to call Google's REST APIs (such as people.get) for more user data, then you need to obtain an OAuth auth code, and exchange it for access and refresh tokens, as documented at https://developers.google.com/identity/sign-in/ios/offline-access

Error on getting authorization URL more than once in Twitter4j

I'm using Twitter4j to implement the authorization workflow on my webapp (user acesses a page, twitter asks permission, I receive the callback and generate the oauth access token).
My first problem was that if I called a method to get the Twitter sigleton:
Twitter twitter = TwitterFactory.getSingleton();
twitter.setOAuthConsumer(getClientId(), getClientSecret());
1) Since OAuthConsumer would already be defined I would get an exception. And I can't find how to ask the singleton if it already has the credentials defined. What's the best way? My solution was to save the singleton in a private member...
2) Now I want to generate an AuthorizationURL, so I need to ask Twitter singleton the OAuthRequestToken:
RequestToken oauthRequestToken = twitter.getOAuthRequestToken(getCallbackURL()); //FIXME
And this throws an exception:
401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.
message - Invalid or expired token.
code - 89
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=3cc69290 or
http://www.google.co.jp/search?q=45a986a5
TwitterException{exceptionCode=[3cc69290-45a986a5], statusCode=401, message=Invalid or expired token., code=89, retryAfter=-1, rateLimitStatus=null, version=4.0.4}
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:164)
at twitter4j.HttpClientBase.request(HttpClientBase.java:57)
at twitter4j.HttpClientBase.post(HttpClientBase.java:86)
at twitter4j.auth.OAuthAuthorization.getOAuthRequestToken(OAuthAuthorization.java:115)
at twitter4j.auth.OAuthAuthorization.getOAuthRequestToken(OAuthAuthorization.java:92)
at twitter4j.TwitterBaseImpl.getOAuthRequestToken(TwitterBaseImpl.java:292)
at twitter4j.TwitterBaseImpl.getOAuthRequestToken(TwitterBaseImpl.java:287)
(...)
Note: the 'Relevant discussions' links are not working as expected I think...
In short:
1) How can I ask the singleton if it already has the credentials defined in order to 'setOAuthConsumer' doesn't throw an error ?
2) How to re-ask the singleton to generate a new authorizationURL for the user to access and authorize (again) ?
Also posted in the corresponding forum
1) How can I ask the singleton if it already has the credentials defined in order to 'setOAuthConsumer' doesn't throw an error ?
There are a few ways that this can be done. You can set the oAuth consumer key and secret in a properties file named twitter4j.properties on your classpath. When you use the TwitterFactory, this is where the default properties come from.
If you want to set the values programmatically, the TwitterFactory also has a few overloaded constructors which allow this:
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.setOAuthConsumerKey(CONSUMER_KEY);
builder.setOAuthConsumerSecret(CONSUMER_SECRET);
Configuration configuration = builder.build();
TwitterFactory factory = new TwitterFactory(configuration);
Twitter twitter = factory.getInstance();
2) How to re-ask the singleton to generate a new authorizationURL for the user to access and authorize (again) ?
I assume that your requirement is to have the user authorize every time. If this is the case, this is handled via Twitters API. There are 2 oAuth endpoints https://api.twitter.com/oauth/authenticate and https://api.twitter.com/oauth/authorize. The authenticate endpoint is the normal Sign in with Twitter functionality where the user will approve once and then automatically logged in every time after. The authorize endpoint will require authorization every time.
Using Twitter4j, these are separate methods that can be called on your RequestToken. You redirect to the appropriate URL based on your requirement.
The solution I've found is presented here:
Twitter instance = new TwitterFactory().getInstance();
instance.setOAuthConsumer(getClientId(), getClientSecret());
RequestToken requestToken = new RequestToken(getOauthToken(),getOauthTokenSecret());
AccessToken oAuthAccessToken = instance.getOAuthAccessToken(requestToken, oauthVerifier);
requestTokenand oauthVerifier are received as parameters in the callback. getOauthToken() and getOauthTokenSecret() retrieve the tokens retrieved by the library in the first step and that were saved in a cache (user -> tokens).
Inspired by this question/answers: Having multiple Twitter instances with twitter4j library.

username is null in DotNetOpenAuth2.ResourceServer.VerifyAccess

I have implemented an authorization server based on the sample and am receiving an access token in response to client credentials request. From my understanding this access token has a null username because it is not tied to a user.
I have implemented a resource server also based on the sample. When I try to validate the access token in my wcf server (resource server) in OAuthAuthorizationManager.VerifyOAuth2 I get an ArgumentNullException for username from
var error = resourceServer.VerifyAccess(httpRequestInfo, out result);
How can I modify OAuthAuthorizationManager to allow a null username?
Do I create a generic principal on the fly and assign it to the scope in the token.
i.e. should I use
var error = resourceServer.VerifyAccess(httpRequestInfo, out userName, out scope);
instead?
This is an issue with DotNetOpenAuth v4.0. v4.1 has this issue fixed. It's not released yet, but you can snag a copy from NuGet if you point it at this channel:
http://teamcity.dotnetopenauth.net:82/guestAuth/app/nuget/v1/FeedService.svc

Resources