Share REST API session cookies with SFAuthenticationSession or SFSafariViewController - uiwebview

Actually, I'm calling REST API services using NSURLSession and I get the session cookies which provided headers. Now I want to share the same cookies with SFAuthenticationSession or SFSafariViewController and load the web page without login.
My Question: Share API cookies and load the web page without login.
Please refer below code to get the cookies from NSURLSession:
NSArray * all = [NSHTTPCookie cookiesWithResponseHeaderFields:[reponse allHeaderFields] forURL:url];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:all forURL:url mainDocumentURL:nil];

Related

Sharepoint REST api - Realm is not a configured realm of the current service namespace error 50169

I got this error trying to get an auth token from Sharepoint REST api. My SP is cloud based and I am using Postman to test the requests, as a previous attempt similarly ran into a dead end when much troubleshooting back and forth with Msoft lead no where .. Anyway, I have the following error and I was wondering if anyone could help me figure out what it is or how I can troubleshoot this issue.
error_description: "AADSTS50169: The realm 'realm' is not a configured realm of the current service namespace"
error_codes : 50169
I followed this tutorial
Thanks!
Edit: I went through and started again, this tut seems to be working I guess I may have missed a step (my guess is I didn't correctly configure the app permissions with xml when creating the app)
To do authorization of SharePoint online and use REST API via Postman, here is a solution for your reference:
First: get security Token
Access [https://login.microsoftonline.com/extSTS.srf] via Http Post method. The content of the http request is as follows.
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd">
<s:Header>
<a:Action
s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>
<o:Security s:mustUnderstand="1"
xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<o:UsernameToken>
<o:Username>[username]</o:Username>
<o:Password>[password]</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<a:EndpointReference>
<a:Address>[endpoint]</a:Address>
</a:EndpointReference>
</wsp:AppliesTo>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
The demonstration screenshot in Postman:
And the response content will include a security token as below, we can use this security token to get Access Token of SharePoint.
Second: get Access Token
Here i show you how to get access token of SharePoint online using the security token and SharePoint Rest API.
Access [https://yourdomain.sharepoint.com/_forms/default.aspx?wa=wsignin1.0] via http Post method. The content of the request is the security token that we have got above as below.
And the response as below:
We can see that there are two cookie, rtFa and FedAuth in response header, and these two cookie need to be added to the request in subsequent request.
Third: get Request Digest
Access [https://yourdomain.sharepoint.com/_api/contextinfo] via http Post method with that two cookies which we have got above.
And the response as below:
This is the final Token we want!
Then we can use REST API of SharePoint, we only need to add this token and the previous two cookie, as shown in the following figure.

Auth0 authentication of single-page-app on a different domain than the api

I'm trying add Auth0 authentication to my single-page-app. My app is running under a domain, say app.mycompany.com, whereas the api used by this app is running under a different domain, say api.mycompany.com.
I'm aware of this thread:
Single Sign On (SSO) solution/architecture for Single Page App (SPA)
and the auth0 articles and github repositories linked by here. But I have a feeling that my scenario is slightly simpler, as I don't necessarily want to have single-sign-on between several different single-page-apps. For a start I just want the seperation between the API and the app.
Here is what I have tried already:
I already started from the article React Login With Auth0 and downloaded the starter project. I can surely login without problems and it will leave me with an id_token in my localStorage containing a JWS issued by Auth0.
I can also login directly on api.mycompany.com (my FeathersJS API application) and I can see that during the OAuth redirecting process, the id_token token is magically translated to a feathers-jwt token issued by my Feathers application containing the internal ID of the user-object matching the auth0-ID. I also have implemented the logic used to map from the Auth0-ID to my internal ID. Furthermore all my Feathers hooks such as validation of token and population of the user are working.
What I cannot figure out is how to alter the react-application running under app.mycompany.com with an Auth0-token in localStorage, so that this token is translated to a feathers-jwt token by api.mycompany.com, in such a way that all succeeding API-calls automatically has the feathers-jwt token included so the API can validate the user and return the right data.
Any suggestions on how to proceed will be greatly appreciated.
A couple of more background details:
The api is built on node.js and featherjs (which basically is an extension of Express)
The single-page-app is built on ReactJS and is served by a simple Express server, but it could be served by any server that can serve static files over http. The single-page-app makes http-requests to the api to read data and perform operations.
The api has the following lines of code taking care of the authentication:
const authentication = require('feathers-authentication');
const Auth0Strategy = require('passport-auth0').Strategy;
app.configure(authentication({
local:false,
token: {
secret: 'mysecret',
payload: ['email', 'auth0Nickname'],
issuer: 'mycompany'
},
idField: 'id',
shouldSetupSuccessRoute: false,
auth0: {
strategy: Auth0Strategy,
domain: 'mycompany.eu.auth0.com',
'clientID': 'xxx',
'clientSecret': 'yyy'
}
}));
I had exactly the same problem as you, I wanted to authenticate a user from a single page application, calling the API located on an other server.
The official auth0 example is a classic Express web application that does authentication and renders html page, but it's not a SPA connected to an API hosted on an other domain.
Let's break up what happens when the user authenticates in this example:
The user makes a request calling /auth/auth0 route
The user is automatically redirected to the Auth0 authentication process (Auth0 login form to choose the provider and then the provider login screen)
The user is redirected to /auth/success route
/auth/success route redirects to the static html page public/success.html, also sending a jwt-token cookie that contains the user's token
Client-side, when public/success.html loads, Feathers client authenticate() method reads the token from the cookie and saves it in the local storage.
From now, the Feathers client will authenticate the user reading the cookie from the local storage.
I tried to adapt this scenario to a single-page application architecture, implementing the following process:
From the SPA, call the authentication API with a source query string parameter that contains the SPA URL. For example: http://my-api.com/auth/auth0?source=http://my-spa.com
Server-side, in /auth/auth0 route handler, create a cookie to store that URL
After a successful login, read the source cookie to redirect the user back to the SPA, sending the JWT token in a cookie.
But the last step didn't work because you can't set a cookie on a given domain (the API server domain) and redirect the user to an other domain! (more on this here on Stackoverflow)
So actually I solved the problem by:
server-side: sending the token back to the client using the URL hash.
client-side: create a new html page that reads the token from the URL hash
Server-side code:
// Add a middleware to write in a cookie where the user comes from
// This cookie will be used later to redirect the user to the SPA
app.get('/auth/auth0', (req, res, next) => {
const { origin } = req.query
if (origin) {
res.cookie(WEB_CLIENT_COOKIE, origin)
} else {
res.clearCookie(WEB_CLIENT_COOKIE)
}
next()
})
// Route called after a successful login
// Redirect the user to the single-page application "forwarding" the auth token
app.get('/auth/success', (req, res) => {
const origin = req.cookies[WEB_CLIENT_COOKIE]
if (origin) {
// if there is a cookie that contains the URL source, redirect the user to this URL
// and send the user's token in the URL hash
const token = req.cookies['feathers-jwt']
const redirectUrl = `${origin}/auth0.html#${token}`
res.redirect(redirectUrl)
} else {
// otherwise send the static page on the same domain.
res.sendFile(path.resolve(process.cwd(), 'public', 'success.html'))
}
})
Client-side, auth0.html page in the SPA
In the SPA, I created a new html page I called auth0.html that does 3 things:
it reads the token from the hash
it saves it in the local storage (to mimic what the Feathers client does)
it redirects the user to the SPA main page index.html
html code:
<html>
<body>
<script>
function init() {
const token = getToken()
if (!token) {
console.error('No auth token found in the URL hash!')
}
// Save the token in the local storage
window.localStorage.setItem('feathers-jwt', token)
// Redirect to the single-page application
window.location.href = '/'
}
// Read the token from the URL hash
function getToken() {
const hash = self.location.hash
const array = /#(.*)/.exec(hash)
if (!array) return
return array[1]
}
init()
</script>
</body>
</html>
And now in the SPA I can use the Feathers client, reading the token from the local storage when the app starts.
Let me know if it makes sense, thank you!
If you haven't done so, you should follow this article (React Login with Auth0) to implement the authentication on your React application. If you already tried to follow it, update your question with specific issues you faced.
Even though you currently not need SSO, the actual implementation of the authentication in your application will not vary much. By using Auth0 enabling SSO across your apps is mostly enabling configuration switches.
Finally for a full reference with all the theory behind the security related aspects of your exact scenario check:
Auth0 Architecture Scenarios: SPA + API
Update:
The full scenario I linked too covers the most comprehensive scenarios where an API is accessed by a multitude of client applications that may even be developed by third-parties that do not own the protected API, but want to access the data behind it.
It does this by leveraging recent features that are currently only available in the US region and that at a very high level can be described as an OAuth 2.0 authorization server delivered as a service.
Your particular scenario is simpler, both the API and client application are under control of the same entity, so you have another option.
Option 1 - Leverage the API authorization through Auth0 US region only (for now)
In this situation your client application, at authentication time, would receive an id_token that would be used to know the currently authenticated user and would also receive an access_token that could be used to call the API on behalf of the authenticated user.
This makes a clear separation between the client application and the API; the id_token is for client application usage and the access_token for API usage.
It has the benefit that authorization is clearly separated from authentication and you can have a very fine-grained control over authorization decisions by controlling the scopes included in the access token.
Option 2 - Authenticate in client application and API in the same way
You can deploy your client application and API separately, but still treat them from a conceptual perspective as the same application (you would have one client configured in Auth0 representing both client-side and API).
This has the benefit that you could use the id_token that is obtained after authentication completes to know who the user was on the client-side and also as the mechanism to authenticate each API request.
You would have to configure feathers API to validate the Auth0 id_token as an accepted token for accessing the API. This means that you don't use any feathers based on authentication on the API, that is, you just accept tokens issued by Auth0 to your application as the way to validate the access.

Token based authentication with flask-security extension

I am currently looking for a way to secure a REST API using token based authentication. I am developing the API in Python using Flask and have discovered the flask-security extension which seems to have a lot of interesting features.
One of the features mentioned in the documentation is Token Authentication.
According to the documentation:
Token based authentication is enabled by retrieving the user auth
token by performing an HTTP POST with the authentication details as
JSON data against the authentication endpoint. A successful call to
this endpoint will return the user’s ID and their authentication
token. This token can be used in subsequent requests to protected
resources.
I am however still a bit confused on how to implement this feature using flask-security.
Some online research has led me to using things such as #auth_token_required but I am having some trouble to put everything together. The flask-security documentation itself is not very helpful.
For example, how can a user get an authentication token? what is the authentication endpoints?
It would be great if you could lead me in the right direction. Code examples would be awesome too :-)
Endpoint is /login, you post your credentials as json request body:
{'email':'john#smit.com', 'password':'1234'}
However for this to work you need to disable the csrf tokens in your flask app (thanks Mandar Vaze):
app.config['WTF_CSRF_ENABLED'] = False
Then you do each request with the token in the HTTP headers:
Authentication-Token:WyI1NTE1MjhmNDMxY2Q3NTEwOTQxY2ZhYTgiLCI2Yjc4NTA4MzBlYzM0Y2NhZTdjZjIxNzlmZjhiNTA5ZSJd.B_bF8g.t1oUMxHr_fQfRUAF4aLpn2zjja0
Or as query string:
http://localhost:5000/protected?auth_token=WyI1NTE1MjhmNDMxY2Q3NTEwOTQxY2ZhYTgiLCI2Yjc4NTA4MzBlYzM0Y2NhZTdjZjIxNzlmZjhiNTA5ZSJd.B_bF8g.t1oUMxHr_fQfRUAF4aLpn2zjja0
Client example in python 3:
import requests
import json
#do the login
r = requests.post('http://localhost:5000/login',
data=json.dumps({'email':'john#smit.com', 'password':'1234'}),
headers={'content-type': 'application/json'})
response = r.json()
print(response) #check response
token = response['response']['user']['authentication_token'] #set token value
#Now you can do authorised calls
r = requests.get('http://localhost:5000/protected',
headers={'Authentication-Token': token})
print(r.text)
Angular example snippet to obtain the token:
$http.post('/login', {"email": $scope.formdata.login,"password":$scope.formdata.password}).
success(function(results) {
$window.sessionStorage.token = results.response.user.authentication_token;
});
Angular example snippet to visit protected pages:
if ($window.sessionStorage.getItem('token')) {
config.headers['Authentication-Token'] = $window.sessionStorage.getItem('token');
}
I found Flask-Security's token-based not a good candidate for my project. I recommend using JWT token instead.
The problems with Flask-Security's token based authentication.
Need to disable CSRF globally, this is not good when you also have a traditional web application in which CSRF token is desirable
No easy way to renew the token ( without submitting password again )
Can not control the payload of the token, there's no API to put/get data to/from the token
That token, by design, only works with one Flask app. So if your frontend app needs to talk with multiple restful apis, this wont work well
Check out JWT (pyjwt or flask-jwt) token, it solves all the above problems and more.
Authentication endpoint is /login
Look at the code of flask-security here specifically views.py: _render_json()
login() calls _render_json which in turn calls get_auth_token() - and returns the auth token.
Problem (for me) is to get this to work.
For me request.json seems empty (hence this does not work)
{"email": "test#example.com", "password": "test123"}
Hopefully this helps you move forward a little.

How to enable server side offline access for Chrome Extension OAuth?

I am working on a Chrome extension where the backend server requires offline access and a refresh token for the user's account. I am not familiar with Chrome extensions, and not sure how I should do the authorization in this case.
The benefit of using chrome.identity is that I can set interactive=false and attempt to authorize without bothering the user when the plugin loads. However, the getAuthToken() method doesn't provide a way for the backend to get a refresh token.
If, instead, I use the launchWebAuthFlow() method and redirect user back to OAuth page, i.e.
chrome.identity.launchWebAuthFlow({
url: https://*<my_host>*/auth/google,
interactive: true,
}, function(url) {
var uri = URI(url),
params = uri.search(true);
var token = params.authToken;
done(token);
});
where https://*<my_host>*/auth/google is my server OAuth path, then for some reason the Permissions scope page doesn't show up. Instead, it shows the Google login page. (Note: if I navigate to https://*<my_host>*/auth/google using the browser, it permissions page shows correctly.)
Is there anyway to do this with chrome.identity API? If not, do I have to do the OAuth using a popup? What's the proper way to do this normally?

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