How do you access the user's bearer token in a ServiceStack service? - servicestack

I have a ServiceStack service which is receiving a bearer token, the bearer token then needs to be passed onto Microsoft Graph for additional API calls from the server side
What is the best way to access this bearer token as a string?
At the moment I am doing my own processing via
var session = SessionAs<AuthUserSession>();
var identityId = session.UserAuthName;
But there does not seem to be a way to access the string bearer token using the Session helpers

The Access Tokens are stored in the UserAuthDetails table which you can resolve the GetUserAuthDetails/Async APIs from your registered IAuthRepository, but if you readily need access to it you can use the AuthEvents that's pre-configured in Auth Enabled templates to access it from IAuthTokens and populate it on your CustomUserSession or Custom UserAuth table.

Related

What is the best way to handle bearer token from external server/api

Hi, currently I'm new to node.js, I have received the token using routes app.post('/getToken'), then later i need the token to call from the external api to get some data and populate it on the front-end. What is the best way to handle the token that i received from the external api.
are there a better way to only call getToken just once, then i can freely get the data from external api by using the token as long the token is not expired and how should i verified the token ?
You can get the bearer token from your request header like this
let bearerToken = req.headers.authorization;
After that you can pass this token to your external API

Docusign UserInfo endpoint returns 401 Unauthorized when access token is provided

I am integrating my API backend with DocuSign in order to send and retrieve envelopes. I am using the JWT Grant flow.
Authentication options
In the DocuSign development environment, I am able to retrieve an access token using the JWT flow and the Docusign C# SKD.
I need to then call the oauth/userinfo endpoint in order to retrieve the base_uri field to use for making calls to Docusign.
When I make a GET request to https://account-d.docusign.com/oauth/userinfo, including the access token in the Authorization header as Bearer <access_token>, I receive a 401 Unauthorized response, and this message in the body:
{
"error": "internal_server_error",
"reference_id": "<some GUID>"
}
I have tried this using curl, Postman and the C# SDK and all give the same result.
Curl syntax:
curl --header "Authorization: Bearer <access token>" https://account-d.docusign.com/oauth/userinfo
user-info endpoint documentation
JWT flow (step 4)
As far as I can see, I appear to be calling the API according to the documentation and I have set up the account with an RSA key pair which is required for system integrations (created within the Docusign admin portal).
Can anyone think of a reason this could be happening?
Since you're using the C# SDK as you mentioned, you can call this endpoint using the same SDK if you have a valid token.
https://developers.docusign.com/docs/esign-rest-api/sdk-tools/c-sharp/reference/
public OAuth.UserInfo GetUserInfo(string accessToken);
You can confirm that your token is valid by trying to use it for other API calls.
A token from the developer account should be useful to make this call in the developer account only. If you need this for production (typically reason to need the base_uri) then you have to call it with account.docusign.com not account-d.docusign.com.
I have now been able to get the base_uri from UserInfo endpoint using the RequestJWTUserToken method in the C# SDK. Using this token allows me to hit the REST API endpoint.
Both methods appear to hit the same oauth/token endpoint and use the same grant type, only RequestJWTUserToken includes the "sub" claim for the userId.

Calling the Graph api after SAML2.0 auth. How do I get the Auth token required

Our web aap is authenticating with the Azure AD via SAML2.0 similar to this.
In return we get SAML assertion(SAML token).
But when the user who logs in have more then 150+ groups the response doesn't contain the group information(so that token size doesn’t exceed HTTP header size limits. More info on this)
But what it return is a Graph Api to be hit to get the group information something like https://graph.windows.net/{tenant id}/users/{user id}/getMemberObject.
By going through this
I understand that I need to attach a Auth bearer token with the http request to hit the graph api successfully.
My problem is how do I get the Auth bearer token?
How can I use the SAML token to get the Auth bearer token?
Other useful link - link1 link2
I've only used the non SAML graph API using the ADAL libraries but from the docs it appears the NameID seems to be the basis for requesting an access token for the Graph API:
<Subject>
<NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">m_H3naDei2LNxUmEcWd0BZlNi_jVET1pMLR6iQSuYmo</NameID>
<SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" />
</Subject>
From this post,
"Here the Client gets a SAML bearer assertion from the SAML Identity
Provider then requests an access token from the Authorisation Server
using the SAML bearer assertion as proof of identity"
and this article states the entire Assertion is used to get the access token, where you:
encode the whole assertion by using base64url encoding before adding
it as part of the POST request
It appears that exchanging a SAML token for a Graph access token is only supported for AD FS, not Azure AD. As per:
This scenario works only when AD FS is the federated identity provider that issued the original SAMLv1 token. You cannot exchange a SAMLv2 token issued by Azure AD for a Microsoft Graph access token.
Source: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-saml-bearer-assertion.
In general, you have to add the OIDC/OAuth stack to your app. As I understand it, this is in addition to your existing SAML authentication implementation. See: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-token-exchange-saml-oauth

Firebase REST auth when creating token with node.js admin sdk

I know this issue was asked a lot here, but I still cannot seem to find the exact answer that can solve my problem.
I wish to access Firebase using REST calls, by adding an access_token param.
The access_token is created using the Node.js Admin SDK, using the following code:
var admin = require("firebase-admin");
var serviceAccount = require("./pk.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://XXX.firebaseio.com"
});
var uid = "1234";
admin.auth().createCustomToken(uid)
.then(function(customToken) {
// Send token back to client
console.log("Token: "+customToken);
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
The problem is that if I take the token created from Node.js and use it my REST call, I get an Unauthorized request error.
I have read in some questions that people added the scope param when issuing the token, but have not found a way to do that with Node.js Admin SDK.
Google's docs are not so detailed with this issue. Any idea what I might try to resolve this one?
The token you are using to authenticate to the Firebase REST API is not the correct type of token. You are using a Firebase Auth custom token, which can only be used to authenticate one of the Firebase client SDKs via the signInWithCustomToken() method as explained in Sign in using custom tokens on clients.
In order to authenticate to the Firebase REST API, you have two options: Firebase ID tokens (for user-based access) or Google OAuth2 access tokens (for admin access).
Authenticate with Firebase ID Tokens
See Retrieve ID tokens on the client for an explanation of how to retrieve access tokens in the various Firebase client SDKs. You can also exchange a Firebase custom token for an ID token and refresh token pair via an undocumented REST API:
Endpoint: https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=<API_KEY>
Method: POST
Request Body: { "token": <CUSTOM_TOKEN>, "returnSecureToken": true }
<API_KEY> is the same API key you get from your Firebase Console that you use in the Firebase clients. <CUSTOM_TOKEN> is a Firebase custom token.
Since ID tokens expire after an hour, you will need to use the refresh token to refresh them via this other undocumented REST API:
Endpoint: https://securetoken.googleapis.com/v1/token?key=<API_KEY>
Method: POST
Request Body: { "refresh_token": <REFRESH_TOKEN>, "grant_type": "refresh_token" }
<API_KEY> is the same API key as before. <REFRESH_TOKEN> is the refresh token from the previous API call.
Once you have an ID token, you can pass that to the REST API via the auth query parameter to authenticate a request. The request respects Firebase Security Rules as if the end user logged into the client was making the request.
Authenticate with Google Access Tokens
To authenticate with a Google OAuth2 access token, the first thing you need to do is get one. See Retrieving an access token for an explanation of how to do this. It only currently includes a Java example, but this is possible in many languages, including Node.js. Once you have an ID token, you can pass that to the REST API via the access_token query parameter to authenticate a request. The request will be made with admin access, overriding all Firebase Security Rules and granting full read and write access.

Web API 2 OWIN Bearer Token purpose of cookie?

I am trying to understand the new OWIN Bearer Token authentication process in the Single Page App template in MVC 5. Please correct me if I'm wrong, for the OAuth password client authentication flow, Bearer Token authentication works by checking the http authorization request header for the Bearer access token code to see if a request is authenticated, it doesn't rely on cookie to check if a particular request is authenticated.
According to this post:
OWIN Bearer Token Authentication with Web API Sample
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
using (IdentityManager identityManager = _identityManagerFactory.CreateStoreManager())
{
if (!await identityManager.Passwords.CheckPasswordAsync(context.UserName, context.Password))
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
string userId = await identityManager.Logins.GetUserIdForLocalLoginAsync(context.UserName);
IEnumerable<Claim> claims = await GetClaimsAsync(identityManager, userId);
ClaimsIdentity oAuthIdentity = CreateIdentity(identityManager, claims,
context.Options.AuthenticationType);
ClaimsIdentity cookiesIdentity = CreateIdentity(identityManager, claims,
_cookieOptions.AuthenticationType);
AuthenticationProperties properties = await CreatePropertiesAsync(identityManager, userId);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
}
The GrantReourceOwnerCredentials function not only compose the ticket with this line: context.Validated(ticket); but it also compose a cookie identity and set it to the cookie with this line: context.Request.Context.Authentication.SignIn(cookiesIdentity);
So my questions are, what is the exact purpose of the cookie in this function? Shouldn't the AuthenticationTicket be good enough for authentication purpose?
In the SPA template there are actually two separate authentication mechanisms enabled- cookie authentication and token authentication. This enables authentication of both MVC and Web API controller actions, but requires some additional setup.
If you look in the WebApiConfig.Register method you'll see this line of code:
config.SuppressDefaultHostAuthentication();
That tells Web API to ignore cookie authentication, which avoids a host of problems which are explained in the link you posted in your question:
"...the SPA template enables application cookie middleware as active mode as well in order to enable other scenarios like MVC authentication. So Web API will still be authenticated if the request has session cookie but without a bearer token. That’s probably not what you want as you would be venerable to CSRF attacks for your APIs. Another negative impact is that if request is unauthorized, both middleware components will apply challenges to it. The cookie middleware will alter the 401 response to a 302 to redirect to the login page. That is also not what you want in a Web API request."
So now with the call to config.SuppressDefaultHostAuthentication() Web API calls that require authorization will ignore the cookie that is automatically sent along with the request and look for an Authorization header that begins with "Bearer". MVC controllers will continue to use cookie authentication and are ignorant of the token authentication mechanism as it's not a very good fit for web page authentication to begin with.
The existence of the cookie also left me puzzled, since it clearly is not necessary in a bearer token authentication scenario... In this post the author dissects the individual accounts template, and has the following to say about the cookie:
The method also sets an application cookie. I don’t see a good reason for that.
My guess is that the authors of the template wanted to show examples of different kinds of authentication logic, and in this particular case they wanted to show how the authentication information could be stored in both the bearer token authentication JSON payload, as well as in a standard authentication cookie.
The fact that the JSON authentication payload is set to also include an additional (unnecessary) unencrypted property (the user id), in addition to the encrypted ticket, seems to support this theory:
var properties = CreateProperties(user.UserName);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
It seems that the authors of the template wanted to provide some useful examples, rather than the bare minimum needed to achieve bearer token authentication. This is also mentioned in the linked post above.
The cookie has one important purpose. Its value contains the bearer token which can be extracted by client-side javascript on your pages. This means that if the user hits F5 or refreshes the page, the cookie will typically persist. Your client-side javascript can then grab the bearer token from the cookie when the page reloads.

Resources