I am using Ping to authenticate users in a Angular/.NET Web API stack, utilizing WIF. WIF works out of the box by just putting in the correct configuration in web.config in a MVC or web Forms application. It intercepts any call to a page/controller requested and if no token available redirects to Ping for authentication.
Q1
In my stack that wont work as the web portion of this application is html/Angular. I could put the Ping configuration into the web api config file and then when angular calls the api, WIF will intercept it and (hopefully) redirect user to ping. But not sure if web api can do a http redirect. Also, pages that probably don't do a api call will load up just fine without authentication...
Q2
Lets say Issue 1 is resolved and user authenticates himself at ping, ping will need to send that assertion to the web api layer and not to html/Angular as it is a POST response. That is fine and web api will check the Claims object to get the user info. After which we will need to redirect the user to go back to the page he was trying to access, which now, app will not know anymore. Also how to achieve http redirection from web api.
Q3
Is there a way for Ping to post to a html/angular page?
Thanks for your help...
Due to the RESTful nature of APIs, they will not be able to do an HTTP Redirect. Even if they could it would be during an AJAX call and not affect the browser.
Out of the box WIF only supports the following protocols:
WS-Fed
WS-Trust
WS-Security
WS-SecurityPolicy
WS-Addressing
I suggest using the OAuth 2.0 Implicit Grant Type for the Angular/WebAPI portion.
That being said, the claims-based identity provided by WIF and OAuth are really complimentary. You could write an OAuth extension for WIF similair to the one referenced here: https://msdn.microsoft.com/en-us/library/azure/gg193416.aspx
This is what I imagine the flow would look like:
Angular app requests information from WIF protected API
API returns status code 401
Angular app performs redirect to Ping OAuth Authorization Endpoint
User Authenticates if they do not already have an existing session with the SSO IdP Server
Bearer token is returned to the Angular app
Bearer token is added to the Authorization header and sent to the API
WIF intercepts the request, extracts the Bearer token and calls the Ping OAuth Token Endpoint to validate the token
Ping returns a token that has the "Claims" information you are looking for, those claims are then injected into WIF.
Related
I am building a React-based SPA that communicates with a spring-boot backend via a REST API. I need the user to be able to log into their Microsoft account on the browser client (the SPA) and I need the backend service (spring-boot app) to be able to query Microsoft's Graph API on behalf of that user.
After reading up on the Oauth2 flows, the authorization code flow (not the PKCE flow, just the regular authorization code flow) seems the most appropriate. The browser client could let the user log into their Microsoft account, retrieve an authorization code, and send the authorization code to our backend service via HTTP request. The backend service (which is trusted and can safely store a client secret) can then request an access token, make requests to the Graph API directly (meaning that the SPA would never need to make any requests to the Graph API), and silently refresh the token as needed.
However, I cannot see any examples of anyone using this flow to access Microsoft's Graph API.
Looking at Microsoft's documentation, it seems like they recommend using the on-behalf-of flow. But this flow requires the browser client to request an access token and then use that to communicate with the backend service (which in turn can communicate with the Graph API). It doesn't make sense to me why the access token cannot be requested on the backend using a client secret. Wouldn't this be a more secure and preferred method than having the client retrieve the access token, as is done in the on-behalf-of flow?
The Oauth2.0 site, recommends that SPAs should either use the authorization code with PKE or the implicit flow, but I do not see an option to use the standard authentication code flow for SPAs. Should I take this as an indication that SPAs should not be using the standard authorization code flow as I described earlier?
Despite not finding a clear-cut example of the standard authorization code flow in Microsoft's documentation for a react frontend + java backend, I tried to go about doing this myself. However, using the #microsoft/mgt-react and #microsoft/mgt-element libraries to do this are not straight forward. For example, the #microsoft/mgt-element notion of a Provider supports a call to retrieve an access token, but doesn't clearly expose the authorization code. If I wanted to do the authorization code flow described earlier, it seems like I would need to use raw HTTP requests, which I know is not a recommended way of accomplishing this.
Summarizing my questions:
What OAuth2.0 flow should I be using: 1) authorization code (access token is retrieved by backend service using client secret), 2)
authorization code with PKE (access token is retrieved by client), or
3) on-behalf-of flow (access token is retrieved by client, seems to be an extension of PKE flow)?
If using the on-behalf-of flow, does the SPA just include the access token in the header (marked as 'bearer') and the backend service just
includes that same header to query the Graph API, or does the backend
service need to request another token before querying the Graph API?
Agree with #ch4mp to call graph api directly in SPA if it's allowed. If not, then I recommend you using on-behalf-flow or client credential flow based on your requirement.
Let's come back to your requirement -- call ms graph api in a springboot api project. First, let's see one of the graph api getting user api. You can see permission types here: Delegated which means call graph api on behalf of the user, Application which means calling api on behalf of the application(your spingboot api project) itself. If you want to call api behalf of the user, then you have to use on-behalf-of flow. This is because the api project which will be considered as a daemon application, so the project itself doesn't have a UI page to let users enter username/password to sign in and get authenticated.
You can certainly use ROPC flow which have to pass the username/password to api but I really think it unsafe, so I don't recommend.
If it's not necessary for you to call graph api on behalf of user, you can certainly take client credential flow into consideration. But pls note here, application type api permission is a "large" api permission which always have name like User.ReadWrite.All, Mail.ReadWrite.All and it always means the application can not only query user information but also be able to modify user information.
If you want to use on-behalf-flow, then you may review this answer and it explained the whole progress...
I would use authorization-code flow (with PKCE) to get an access-token and then refresh-token flow to "maintain" this token, both from client.
Authorizing the request to your resource-server with this token only makes sense if Microsoft authorization-server is your main authorization-server. Otherwise (user also logged in with an authorization-server of your own or not using OAuth2 betwean React and backend), you can still send Microsoft access-token in request body.
In any case, when issuing requests in the name of the user from the backend, do as you suggest: just set the access-token sent by the client as Bearer Authorization header (token is retrieved either from Spring security context or request body). Backend fetches a new access-token (using client-credentials flow) when issuing requests in its own name (without the context of a user).
Side note: have you considered calling Microsoft API directly from React client? If you don't have to store the result of that call on your resource-server (i.e. call graph API to display data and store only what user selected from that data), that would save quite some latency on the client and costs (network and CPU) on the backend.
I have a scenario where I have an on-premise GUI application which has a "Web Service Invoke" component which I use to call a GAE API.
In the GUI application, it is possible to:
store credentials
create a chain of web services/http(s) calls that can integrate an output of preceding https(s) call as a query parameter or header value into the next http(s) call
retrieve a value from JSON response of the http(s) call
But it is not possible to programmatically do anything. The Web Service widget has fields for passing API URL, query parameters and headers only.
I'm looking to do a service-to-service authentication for the API call and the API should be protected using IAP as well.
I'm aware of the recommended approach is to create a service account and provide the service account JSON key file to the client and the client signs a JWT token and pass it as a bearer token. But as I only have widgets, no programming possible, therefore signing JWT token is not an option.
I was looking at Google OAuth or IAM APIs which can support "client_credentials" grant type wherein I can get an access token using just clientId and clientSecret - something possible in Apigee. But it seems this grant type is not supported by Google OAuth APIs.
I also looked at Cloud Endpoints using API KEY - so the current thought is to the client passes API KEY in header/parameter for authentication to Cloud Endpoints, then Cloud Endpoints uses its service account to get access through IAP, and finally, I'm thinking that the client can also send in "Basic Auth" credentials through Authorization header which the GAE API backend service validates. The additional "Basic Auth" is because Google recommends using another auth method in addition to API KEY.
I would like a simpler solution if possible using GAE and IAP only. Any other suggestions, especially using time-limited tokens, that can work over only http(s) calls (non-programmatic or client library), is much appreciated.
Any alternatives or things to try is also appreciated.
Look into this server-to-server authentication using JWT Google API Authentication
I have a web app developed using Create-react-app
I host it on IIS, the IIS only response to load the app, there is no server side logic on it (no Express or any other web server)
The app is using a RESTful API on the same IIS, it is out of my control (I cannot make change).
Now one of my client request to add SAML SSO to our app.
I would like to know:
in normal situation, which one is the Service Provider? My IIS Web server? or the API service?
For my case, I cannot implement SAML to API service, my web service only used to load my app without server side logic, how can I implement SAML?
Could any one give me some React implement SAML SSO tutorial or article for reference?
Thanks for any help, any information or suggestion are welcome!
in normal situation, which one is the Service Provider? My IIS Web server? or the API service?
I assume the client wants to authenticate the users using their internal IdP. So your application is the SP. But you will have to define different token service (details below).
With SPA (a single-page-applications) I see the problem, in SAML the user is redirected or posted away from the SAML request and SAML response.
I have a login page to enter id/pw, post them to API server Login endpoint to authenticate and get back a JWT token. After that we use that token in API calls for authentication
The API services are using a JWT token issued based on the provided username/password. I'd recommend to extend the token service (or use a different service) to issue a JWT token based on the provided SAML response - a token swap service. In many OAuth implementations it's called SAML grant type.
I cannot implement SAML to API service, my web service only used to load my app without server side logic, how can I implement SAML?
Usually after the authentication the user is redirected or posted to the SAML ACS endpoint URL, where the server can create sort of session (cookie, parameters, token, ..) and the user is redirected to a URL returned the web page with the session information.
If you are using an SPA, you could use a popup window or SAML with redirect (not with post), where the page could read the SAML response parameters (assertion, signature, ..) and use them in the token swap service mentioned above.
When processing the SAML response, try to use some mature, known, out-of-box libraries, it's a security service and not doing it properly may cause security weaknesses. But you need to do that on the server side, as at the end you need the JWT token consumed by the APIs.
Using Express and Passport JS on the backend we are currently able to login to the application, and access all of the API requests using postman.
However when we try and make API requests that require authentication on the React JS Web Application we get a 401 unauthorised error.
We've run logs from both the postman request and the web app request and both are passing the connect.sid cookie in the header.
My question is, how do I get the application authenticated and able to make API requests like postman can. I login to postman the same way I do using the web application but it doesn't authenticate the api requests.
Things I've tried:
manually setting the headers to allow cross origin requests
setting an Authorize bearer token
Specifying on the backend the origin of the front end, which only allows api calls to be made from the front end web server
The application is a ReactJS application, and I am making the API calls using Axios
I fixed this by passing withCredentials on login, this sends your user to the passport.js and authenticates the user.
You need to call withCredentials every time you make an API call though
We have developed a web application using angularjs and web api. The application is deployed in IIS 8.5. Users are in AD domain, our site is added in local intranet zone and also selected automatic login only in intranet zone option.
We are using web api token based authentication using OWIN in our application. So we disabled all IIS authentication methods other than anonymous authentication. The token will be generated at the server side while login to the application and this token will send back to the client side. We are saving this token in sessionStorage and will attach in the http request header like "Authorization : Bearer auth_token".
But in some times, mostly if we wait more than 1 minute, we could see that "Authorization: Negotiate some_token" is sending in our api calls. So the server will respond with a 401 unauthorized error.
Anybody experinced in same?
Thanks in advance
We were able to avoid this issue by applying
document.execCommand('ClearAuthenticationCache', false);
in our app.js file.
By enabling anonumous authntication at the rool level also solves our issue.