I have a client-side web app (no backend) that uses Google Javascript API.
I have an issue regarding the access-token that I got after the login is successful.
From the callback, we can see that the access-token is set to expire in 1 hour.
expires_in: "3600"
Question is, how can I "get a new token"?
From the documentation, I'm under the impression that after the token is invalid, we have to (and I quote) perform a new re-authorization flow with immediate set to true to get an up-to-date access token.
Source:
https://developers.google.com/+/web/api/javascript
However, when I tried to call again the auth method:
gapi.auth.authorize(parameters, callback)
I got the token object, but there's no access-token inside.
{
client_id: "{my_client_id}.apps.googleusercontent.com"
cookie_policy: undefined
expires_at: "1370371466"
expires_in: "86400"
g_user_cookie_policy: undefined
issued_at: "1370285066"
response_type: "token"
scope: "https://www.googleapis.com/auth/plus.login https://gdata.youtube.com"
}
Am I missing something? How do we usually get a refreshed token after one expired?
On client side, access token is temporary. This is by default online access to user resources. In order to get access tokens again, you need to redirect user for permissions again.
In the OAuth protocol, your app requests authorization to access resources which are identified by scopes, and assuming the user is authenticated and approves, your app receives short-lived access tokens which let it access those resources, and (optionally or more precisely on server side) refresh tokens to allow long-term access.
for server side apps and for offline access of user resource you need to have refresh token Refer to: Google Analytics API Automated Login
Also read: https://developers.google.com/accounts/docs/OAuth2WebServer
https://developers.google.com/accounts/docs/OAuth2UserAgent
Related
I'm creating a simple web app that needs to call an Azure Function.
I've registered 2 apps in my Azure AD: one for my single page react application and another for my Azure Function.
The app for my azure function has an API exposed on it and a scope configured called CallApi.
The app itself has authentication configured on it (easy auth), and the client id matches the API app registration within AAD:
The app for my SPA has permission to request this scope and this is granted by default for all users.
I am able to successfully log users into my SPA and get an access token. I'm doing this with the use of the #azure/msal-browser and #azure/msal-react npm libraries, specifically:
<MsalAuthenticationTemplate interactionType={InteractionType.Redirect} authenticationRequest={{scopes: ["User.Read", "api://<redacted>/CallApi"]}} >
However, the access token that is returned only has these scopes: ['openid', 'profile', 'User.Read', 'email'] and not api://<redacted>/CallApi. So when I try to exchange my access token for a token by sending a POST request to https://<app_name>.azurewebsites.net/.auth/login/aad it returns an unauthorized message.
How can I ensure that the CallApi scope is allow by my app?
So when I try to exchange my access token for a token by sending a POST request to https://<app_name>.azurewebsites.net/.auth/login/aad it returns an unauthorized message.
Please ensure that the URL is correct as it should be in the format of <app-url>/.auth/login/aad/callback and note that the parameters are in the body of the HTTP POST request.
However, the access token that is returned only has these scopes: ['openid', 'profile', 'User.Read', 'email']
openid
If an app performs sign-in by using OpenID Connect, then it must request the openid scope. That is to say, the openid scope displays on the work account consent page as the “Sign you in” permission.
email
The email scope can work with the openid scope. As it gives the app access to the user’s primary email address in the form of the email claim. Where, the email claim is included in a token only if an email address is associated with the user account, which isn’t always the case.
profile
The profile scope can also work with the openid scope. This gives the app access to a substantial amount of information about the user. The information that it has access includes, the user’s given name, surname, preferred username, and object ID.
In the Microsoft ecosystem there are some high-privilege permissions that can be set to admin-restricted. This include:
Firstly, read all user’s full profiles by using User.Read.All
Secondly, write data to an organization’s directory by using Directory.ReadWrite.All
Lastly, read all groups in an organization’s directory by using Groups.Read.All
Please refer this article for an example regarding the POST request regarding the Call API Scope.
Need help with the below-faced issue in the implementation of Keycloak redirection in the flutter web application.
Flutter Package Used : keycloak_flutter | Flutter Package
The above package has used Keycloak JS adapter implementation. to achieve keycloak redirection in the flutter web application using the below reference.
Reference : Securing Applications and Services Guide
Describe the bug :
Using the package I am trying to refresh the access token by calling the update token method which makes the refreshtoken API request from keyclaok.js. but the request returns Status 400 Bad Request, then I checked the request in the browser tool(network tab), and the refresh_token is passed as undefined. I also tried to pass -1 as a parameter to the update token() which forcefully refresh the token.
access_token expires in 1 min
Expected behavior :
The update token method should refreshtoken if the access token is expiry.
Also Observed
Immediately after successfully login OnAuthLogout event is fired
the token expired event is not fired even after the token is expired
Thanks in Advance.
I have a scenario where my API updates some claims in active directory via the Graph API.
In such case, I notify the client via response headers that it needs to refresh the access token, in order to get a token with the new claims.
The problem is that when I call acquireTokenSilent (in Msal.UserAgentApplication) in gives me the old token. I found out that it happens because Msal saves the access token in sessionStorage/localStorage.
Is there a way for me to explicitly request a new access token without directly removing the cache?
acquireTokenSilent method will acquire and renew tokens silently in the background. The access token will expired in an hour by default. After 1 hour, you will get a new access token. You can refer to this document.
Usually we can use the refresh token to refresh access token. But in msal.js this is not transparent. Anyway, you can have a look at this answer.
You can sign out and sign in again. Then you will get a new access token.
You can also call acquireTokenPopup or acquireTokenRedirect method to acquire a new access token, but they are interactive methods.
Refer to How to renew tokens with MSAL.js for more details.
I am creating a login page. The idea is to take the username and password then use that to get an id token from AWS cognito user pool.
Then I need to store the token in a database and transfer that token to index.html along with the username. This is because index.html needs the token to make a post request to an API gateway using the same id token and it needs to know the user name to keep track of which user is currently logged in.
Now the index.html has to check if the token transferred to it matches the token in the database or not.
If it does and the token is not expired, then there is no redirection, otherwise, the index.html redirects to login.html.
The problem is my back-end completely relies on Amazon Lambda functions and API gateways because my company does not want me to use any back-end language. Now, I found that lambda functions could not set browser cookies nor read browser cookies.
This left me no choice but to use javascript cookies, sessions and local storage to transfer the token and username to index.html. However, this approach is considered to be insecure.
There aren't any tutorials on a secure login system using cognito.
Note: Any other secure login system will do the work, but remember I need to pass username and password to user pool to get an ID token which means, if I use any other login method, then I would now need to pass username and password both to index so that index can make a request to user pool to get an id token and make a request to the API gateway.
Now my question is, is there a way to actually transfer data to index from login without compromising security? Can I use lambdas in any other way to transfer the tokens?
Please help. Thanks in advance.
Now, I found that lambda functions could not set browser cookies nor read browser cookies.
I don't think this is strictly true.
Using Lambda Proxy Integration gives your Lambda function visibility into and control over many aspects of the HTTP request. This includes setting and reading arbitrary headers (including set-cookie).
To demonstrate, you can set a function like this up and attach an API Gateway trigger (with Lambda Proxy Integration enabled) to it:
exports.handler = (event, context, callback) => {
var returnobj = {
"statusCode": 200,
"headers": {
"Content-Type": "application/json", "access-control-allow-origin": "*",
"Set-Cookie": "testcook=testval; path=/; domain=xxxxxxxxxx.execute-api.us-east-1.amazonaws.com; secure; HttpOnly"
},
"body": JSON.stringify({})
};
console.log("headers", event.headers.Cookie);
callback(null, returnobj);
};
This function returns a Set-Cookie header that the browser will respect and send along with future requests to this domain. If you hit this in a browser twice, you'll see the cookie sent by the browser and logged by the lambda on the second request.
If you aren't willing to use Lambda Proxy Integration, you can probably still pull this off by mapping part of your Lambda response to a header in API Gateway.
I'm using the adal-angular library (but not with Angular) in my SPA to try to acquire an access token that I can use to call the SharePoint APIs (https://<my-tenant>.sharepoint.com/_api/).
I've registered an application in Azure AD and enabled the implicit flow in the manifest, and I'm now running my SPA locally, which is why there's a localhost redirect URI. The code below is being executed on startup:
const context = new AuthenticationContext({
clientId: '<my-client-id>',
redirectUri: 'http://localhost:3000/signin',
popUp: true,
loginResource: 'https://<my-tenant>.sharepoint.com',
callback: () => window.location.reload()
});
const user = context.getCachedUser();
if (!user) {
context.login();
} else {
context.acquireToken('https://<my-tenant>.sharepoint.com', (error, token) => {
console.log(error, token);
});
}
I'm already logged into the SharePoint site, so with this config everything happens automatically and I see a JWT access token logged to the console. However, when I inspect the token, I see that the audience is <my-client-id>. When making a call to https://<my-tenant>.sharepoint.com/_api/v1.0/me using the access token, I then get a 401 response with the following error message:
{"error_description": "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
I'm pretty sure this all boils down to me not understanding the OAuth2 flow properly, but... how can I acquire a token that SharePoint can actually be used with SharePoint? Am I thinking about this the wrong way? It kinda defeats the purpose if the token retrieved by my app can only be used to authenticate against my own app.
Getting an access token to SharePoint is well described here:
OneDrive for Business authentication and sign in
You should consider first getting a token to the Discovery Endpoint:
Using an access token received for resource
https://api.office.com/discovery/ you can make a request to the
discovery API to learn which services are available
If the call is successful, the response body contains JSON data with
information about the services available for the user and your app.
{
"#odata.context": "https:\/\/api.office.com\/discovery\/v1.0\/me\/$metadata#allServices",
"value": [
{
"#odata.type": "#Microsoft.DiscoveryServices.ServiceInfo",
"capability": "MyFiles",
"serviceApiVersion": "v2.0",
"serviceEndpointUri": "https:\/\/contoso-my.sharepoint.com\/_api\/v2.0",
"serviceResourceId": "https:\/\/contoso-my.sharepoint.com\/"
}
]
}
There you should get your valid Resource ID... but the issue here may just be that you did not include a forwardslash (/) at the end of the Resource URL in your sample code.