Can't seem to find anything that makes FusionAuth send a signal to applications to terminate a user's session upon signout.
FusionAuth provides an API at /api/logout that might work. This API will revoke any refresh tokens that the user has. When refresh tokens are revoked, FusionAuth will send an event out to any configured Webhooks.
Here is the documentation on this API, Webhooks and the event that is fired:
https://fusionauth.io/docs/v1/tech/apis/login#logout-a-user
https://fusionauth.io/docs/v1/tech/events-webhooks/events#jwt-refresh-token-revoke
https://fusionauth.io/docs/v1/tech/events-webhooks/writing-a-webhook
Here are the rough steps you can take to get this working:
Create a logout endpoint in your application or in a new microservice (https://example.com/global-logout)
This endpoint calls the /api/logout endpoint in FusionAuth
Each application that wants to be notified then writes a Webhook and handles the jwt.refresh-token.revoke event
You can see an example Webhook in the documentation link about. A Webhook that handles the jwt.refresh-token.revoke event might look like this in Node/JavaScript:
router.route('/fusionauth-webhook').post((req, res) => {
const request = req.body;
if (request.event.type === 'jwt.refresh-token.revoke') {
// Clean up all the user's stuff here
}
});
Related
I am creating a webhook handler (within aws lambda) for my shopify app.
Note: I'm using eventbridge to receive webhooks, but i believe the concept is the same.
When a customer creates a new order this webhook will be called, and from within my webhook handler i would like to make an authenticated request to the Nodejs #shopify/shopify-api Admin API.
My question is, what is the best way to do this?
For example, how do i use the details from the webhook event to create a session which i can then use to make requests to the Admin API?
eg;
const product = await shopify.rest.Product.find({session, id: '7504536535062'});
product.title = 'A new title';
await product.save({
update: true,
});
the webhook comes from a store! So you know the *.myshopify.com
you saved an access token with the same store name in your DB
So now you can use the access token against the store, to make API calls within the scope of permissions granted when the store installed the App.
I'm using a server that authenticates through keycloak. In keycloak I have created a realm and am able to get an Access token as a response. This access token gets fed now into my Ktor application.
However, I'm not quite sure how to protect routes in an easy manner. I want to have some protected routes that have a authenticate("keycloakOAuth"){} scope around it which handles validating the access token and refreshing using the refresh token if the access token is expired.
Currently I have keycloak inside Ktor configured as this:
authenticate("keycloakOAuth") {
get("login") {}
route("/callback") {
// This handler will be executed after making a request to a provider's token URL.
handle {
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
if (principal != null) {
val response = principal as OAuthAccessTokenResponse.OAuth2
call.respondText { "Access token: ${response.accessToken}" }
} else {
call.respondText { "NO principal" }
}
}
}
}
This works fine because when I go to login I'm getting sent to the Keycloak login page and I can login. When I logged in the callback executes and I get my Access Token back.
When I'm trying to protect routes however, some odd stuff happens. I know that I need to validate the incoming JWT token. But I have no clue how to given the Ktor capabilities. The examples are also of little help, since they are quite vague.
Currently I have something like this:
authenticate("keycloakOAuth") {
get("/testAuth") {
val principal = call.authentication.principal<OAuthAccessTokenResponse.OAuth2>()
if(principal != null) {
call.respondText("Authenticated!")
} else {
call.respondText("Unauthenticated...")
}
}
}
But my application will always send me to the login page and then callback page, even though I am sending the Bearer token when I'm testing this call.
My question is:
How do I protect routes in a manner that they need a valid token, with the same syntax that Ktor uses (like authenticate(){}). Do I need to configure JWT for this?
When you request one of the routes under authenticate, the full cycle of OAuth authentication is triggered. This is because the Authentication plugin is designed so a client sends credentials and gets authenticated for each request. For some reason, OAuth integration was implemented on top of the Authentication plugin hence such unexpected behavior.
To solve your problem you can have only /login and /callback routes restricted. In the callback's handler save user ID and tokens in a session or in any other storage for future use. For other routes, you can check manually the fact that a user is authenticated and then use tokens from storage to acquire protected data from the resource server. For convenience, you can create some extension functions to minimize the amount of boilerplate code. Unfortunately, there is no built-in functionality to make it work out of the box.
You don't need to configure JWT for this.
I’m in process of developing system which consists from such parts:
- Some services under gateway (Ocelot)
- Mobile client (iOS)
- Identity Server 4
Mobile client hasn’t been prepared yet, so I use Postman for emulating requests from it. My problem is implementation of Authentication with External providers, like Google. It’s my first experience of using IS 4, so I have some misunderstanding and difficulties. Excuse me, if my question is too abstract or if I miss smth obvious.
I successfully deployed IS 4 using all this tutorials and it works with Password Credentials flow in a proper way: I request IS for access token, sending user credentials, it returns token and I can successfully use it for access to my API methods.
Situation with External Providers are different. I’ve overviewed this tutorial (https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-3.1) and some other and add code from it to the IS project. I can successfully log in with Google, using a button on that IS4 web-page which goes with IS 4 Quickstart UI template. But no chance to work with API. As I understand in such workflow client-app should go for a token not to my IS as in example with a local user, but to the Google Auth provider. And I emulated it with Postman and got a strange access_token which has no data and it_token which contains username, email and so on. I try to use this id_token with requests to my API. The result is always 401.
Where I’m wrong? How should I build requests to API with token from Google? Or I have misunderstanding and there should be another flow: client goes to IS with specific request, IS goes to Google and then returns proper token to Client?
Here is configuration of authecation on the side of Web API app:
private void ConfigAuthentication(IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.Audience = "k_smart_api";
});
}
Here is config of Google-Auth on the side of IdentityServer:
services.AddAuthentication().AddGoogle(opts => {
opts.ClientId = "My google client Id";
opts.ClientSecret = "my google client secret";
opts.SignInScheme = IdentityConstants.ExternalScheme;
opts.SaveTokens = true;
});
This is how I get Access Token:
postman exampple
The tokens you get back from Google, is only used to Authenticate the user in Identity Server. Then after Identity Server receives those tokens, it sign-in the user and create new tokens (ID+access) that are passed to your client. you should look at using the authorization code flow in your client to authenticate the user and to get the tokens. then use the access token received to access your API.
do remember that the tokens received from Google are not used to give access to your APIs.
I'm unable to authenticate / sign-in via AzureAD when running testCafe.
const testrole = Role(
'https://login.microsoftonline.com/',
async t => {
await t
.typeText(Selector('input').withAttribute('type', 'email'), *******)
.click(Selector('#idSIButton9'))
.typeText(Selector('input').withAttribute('type', 'password'), ********)
.click(Selector('#idSIButton9'));
},
{ preserveUrl: true }
);
The above steps work fine, however after entering the password I get a message saying:
"Unable to sign in to Outlook account, Error: AADSTS900561: The endpoint only accepts POST requests. Received a GET request."
From my initial search, it seems like something to do with 3rd party cookies on the browser. However, I'm unable to find a solution at this time.
Any idea how I get around this issue?
The Azure AD product team has always reminded me that it is a bad idea to try to automate sign in like that.
They will probably detect that you are a bot and start blocking your requests, even if you succeed.
Instead, to acquire access tokens you need to use either the client credentials flow (for app-only tokens) or the resource owner password credentials flow (for delegated user tokens).
Client credentials flow: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
ROPC flow: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth-ropc
You have to take good care to secure the credentials used for testing.
And use a test tenant if possible.
I would like to let my users sign up for my laravelbased application using facebook or similar through socialite.
My users use a mobile app on their smartphones, which accesses the API of my app. Those API-routes are currently secured through the auth.basic middelware
Route::group(['prefix' => 'api/v1', 'middleware' => 'auth.basic'], function()
{
// ...
});
The app interacts with the api restfully through basic protected urls..
https://user:pass#myapp.com/api/v1/item/1
Now, how can i enable my users to access my protected api-routes, when they have registered through socialite? Is there a Package or a predefined middelware? Also, how would the URLs look like? Is it even possible to allow API calls with both, normally registered users and those being registered through socialite at the same time?
I see 2 best options in here.
Easiest is to use simple auth middleware in combination of logging in to the API at first before any other API calls
Secondly you can create custom middleware and include a token in your API call that authenticates the user. Example of such call after logging and getting token is below. Middleware gets the url param and checks if this is correct.
https://myapp.com/api/v1/item/1?token=123456