Do API Connections retain their authorisation state indefinitely? - oauth-2.0

I've created an Azure Automation API Connection to use in a Logic App action. As the docs explain, when the API Connection is first created it requires authorisation before it can talk to Automation:
PS C:\> $conn = Get-AzResource -ResourceGroupName my-rg -ResourceType Microsoft.Web/connections -Name azureautomation
PS C:\> $conn.Properties.statuses
status target error
------ ------ -----
Error token #{code=Unauthenticated; message=This connection is not authenticated.}
Following the docs I can open the connection in the Logic App Designer and authenticate as a user with permissions to create Automation jobs (e.g. one with the Automation Job Operator role). The connection then shows as authenticated and the action successfully creates jobs:
PS C:\> $conn = Get-AzResource -ResourceGroupName my-rg -ResourceType Microsoft.Web/connections -Name azureautomation
PS C:\> $conn.Properties.statuses
status
------
Connected
PS C:\> $conn.Properties.authenticatedUser
name
----
username#example.com
Clearly the connection hasn't just been authenticated, it's also been authorised. What's not clear to me is which authentication flow the Logic App Designer has followed, and in particular whether the connection will automatically refresh its access tokens without further intervention. This isn't just academic: what I want to know is will the connection silently lose authorisation at some future point?
I'm building this for a customer who's new to Azure, so I want to keep the solution as simple as possible. They're familiar with the idea of a service account in the on-prem AD world, but AAD service principals are new to them. Is it safe to rely on one-time manual authorisation through the Logic App Designer, or is using a service principal the only reliable way to ensure the connection stays authorised?

I think using a service principal is more reliable in your scenario, if you use a user account to authorize the connection, the connection maybe broken as an undetermined issue e.g. the password changed in the future. If you use the service principal to authorize, we just need to use a never expired client secret, then it will never lose authorization.

Related

Newly deployed cloud run app inaccessible, despite having requisite permissions (403)

Following this quickstart guide (Python version), I was able to quickly create and deploy a Python Flask app to a project owned by my organization. However, toward the end the guide instructs "Visit your deployed container by opening the service URL in a web browser", and but this is the step I can't get to work.
Curiously, in the logs
(https://console.cloud.google.com/logs/) the 'textPayload' data element for the request is "The request was not authenticated. Either...", which seems unusual, as I'd expect an unauthenticated request to return 401, not 403. In any case, it does not list my org email address in the request, suggesting my identity for some reason isn't being supplied. Any way to fix this so I can access the URL using a user with appropriate permissions?
Note: I can access the URL by manually running "curl -H 'Authorization: Bearer <my token>'"
Cloud Run URLs aren't directly accessible if the service only allows authenticated invocations because passing the URL on your browser will not generate the credential for you. You will have to pass auth credentials on your request and the easiest way to invoke the service is to use a tool like curl which is exactly what you noted.
You have two options to authenticate your end users which are the following:
Integrate Google Sign-In.
Implement Identity Platform or Firebase Authentication.
In either of the above choices, you need a public web or mobile app that handles the sign-in flow and then makes authenticated API calls to a Cloud Run (fully managed) service.
For more information on authenticating end users, check out the official documentation.
To complement what Mr. Donnald Cucharo said, you can also use Identity Aware Proxy (IAP) to expose your application in a secure way.

Authentication in service worker

I'm dabbling into the art of service workers and PWA. I have trouble finding out more about authentication for the service worker. I want to poll or have a websocket to a backend, where i would need to authenticate. The service worker would be registered within the same domain and enabled when the user is already authenticated. But what happens when the user closes that session, will the service worker still work with the login cookie?
If the user closes the session/logs off then any Fetch request the SW performs that requires authentication will fail.
FYI, I asked about Session Expiry without a client present, as opposed to the user actively terminating the session here
Sadly the only work being done on SW at the moment is caching everything, offline-first, over-tuning, and "Look! I've built a proxy-server and CloudFlare on the client" :-(

How to log in the HyperLedger Composer webApp with different user other than admin

I just started building a relatively simple supply-chain app by using HyperLedger Composer webApp. In my permission file, I will have several participants that specify which role can do what. It's easy to switch role inside the playground through the wallet. However, I can't find a way to switch at my Angular webApp.
I thought it can be called through the System endpoint in the composer REST Server. But when I trying to "GET" from the /system/identities nothing show up, even I have created several participants. Can someone enlighten me with some examples?
Thank you guys so much!
Developing multi-user application using the Hyperledger Composer REST Server
Firstly, some quick background. What is Hyperledger Composer? It’s a framework for rapidly building Blockchain business networks on top of a Blockchain platform, such as Hyperledger Fabric. It’s pretty cool. You can find some more information here: http://hyperledger.github.io/composer/
Blockchain is a technology for building networks that connect organizations together. Once started, a Blockchain network allows participants to transfer assets between each other by submitting transactions, and those transactions are recorded in an immutable ledger.
So once you have your Blockchain Network how do you integrate with your client application? One solution would be to call the Hyperledger Composer JavaScript APIs directly or you could use the Hyperledger Composer REST Server in multi-user mode.
The Hyperledger Composer REST Server will generate a set of REST endpoints from a Hyperledger Composer Model. The endpoints can then be called from a client application to interact with a Blockchain. When the client applications calls one of the REST endpoints, the REST server will then submit a transaction to the Blockchain. This transaction must be signed by a certificate to say which identity is being used to submit the transaction. When the REST server is started it must be given a identity to use and by defaults all transactions will be signed with this identity.
The REST server can be configured to use authentication. This allows a client application to authenticate with the REST server and then the REST server can distinguish between each of the clients.
However this still doesn’t allow the Blockchain to distinguish between clients. The REST server will still sign each transaction with the same certificate. To enable the REST server to sign each transaction with a different identity per authenticated client the REST server must be configured to use multi-user mode. Each authenticated client will then have a private wallet on the REST server that contains the identity that will be used to sign the transaction on behalf of the different authenticated clients.
This article shows how to configure the REST server for multi-user mode and how it can be called from a client application to add participants and identities and how to submit transactions that are signed by different identities. The client app is written using Angular and will use GitHub authentication to authenticate itself with the REST server. This is just one example of the type of authentication that can be used. The REST server uses an open source library called Passport and there are over 300 plugins that are available to use, eg. LDAP, Facebook, SAML, and Google.
If you haven’t downloaded Hyperledger Composer you can follow the instructions to setup your development environment here: https://hyperledger.github.io/composer/installing/development-tools.
Once you have the development environment setup you firstly need to create and deploy a business network. The one I have used in this article can be found here: https://github.com/caroline-church/collectable-penguin-app/blob/master/collectable-penguin-network.bna. The client app used can be found here: https://github.com/caroline-church/collectable-penguin-app. The app allows users (Collectors of penguins) to sign up and to buy penguins from a “wholesaler” and each user has their own set of penguins which they have bought.
To setup the app you first need to add an OAuth application to GitHub here: https://github.com/settings/developers.
The app needs to have two REST servers running. The first has no authentication and will run in single user mode. This REST server will just be used to create participants and identities when users sign up to the app. It can be started by using the following command.
composer-rest-server -c admin#collectable-penguin-network -p 3001
The second REST server will run in multi-user mode. Firstly you need to set an environment variable to set some properties for the REST server. The and properties can be found in the github OAuth app that was created previously. The successRedirect property is set to the url of where app is running.
export COMPOSER_PROVIDERS='{
"github": {
"provider": "github",
"module": "passport-github",
"clientID": "<CLIENT-ID>",
"clientSecret": "<CLIENT-SECRET>",
"authPath": "/auth/github",
"callbackURL": "/auth/github/callback",
"successRedirect": "http://localhost:4200?loggedIn=true",
"failureRedirect": "/"
}
}'
Once the environment variable is set then the second REST server can be started with the following command
composer-rest-server -c admin#collectable-penguin-network -m true
The client app can then call the REST endpoints. To start the user needs to authenticate with GitHub. This can be done be having a link on the page, the URL is the URL of the multi-user REST server e.g
Sign in with github
Then the user needs to sign up to the app. This data can then be used to create a participant and identity. In this case a Collector participant will be created.
The following will create a Collector participant using the single user REST server
return this.httpClient.post('http://localhost:3001/api/org.collectable.penguin.Collector', collector).toPromise()
The body of the post should be the data the user supplied e.g.
const collector = {
$class: 'org.collectable.penguin.Collector',
collectorId: 'carolineId',
firstName: 'Caroline',
lastName: 'Church'
};
Once the participant has been created then an identity can be issued for that participant, again using the single user REST server. The response type must be set to blob as this endpoint returns a business network card.
return this.httpClient.post('http://localhost:3001/api/system/identities/issue', identity, {responseType: 'blob'}).toPromise();
The body of the post should include the ID and participant created previously e.g.
const identity = {
participant: 'org.collectable.penguin.Collector#carolineId,
userID: carolineId,
options: {}
};
The newly created identity can then be added to the wallet of the multi-user REST server. The card from the previous call to the endpoint is used to create a new file object, this file object is then used to create some formData. A header is added to the request to set the content type to be multipart/form-data. The wallet import endpoint can then be called with the data. The withCredentials option is set in-order to create a cookie to pass the authentication token to the REST server.
const file = new File([cardData], 'myCard.card', {type: 'application/octet-stream', lastModified: Date.now()});
const formData = new FormData();
formData.append('card', file);
const headers = new HttpHeaders();
headers.set('Content-Type', 'multipart/form-data');
return this.httpClient.post('http://localhost:3000/api/wallet/import', formData, {withCredentials: true, headers}).toPromise();
Now the client is authenticated with the REST server and an identity has been added to the wallet the endpoints can now be called. The REST server will submit transactions that are signed with the identity that was previously added.
For example the following HTTP request will get all the available penguins
return this.httpClient.get('http://localhost:3000/api/queries/availablePenguins', {withCredentials: true}).toPromise();
And the next HTTP request will get the penguins that the authenticated user owns
return this.httpClient.get('http://localhost:3000/api/queries/myPenguins', {withCredentials: true}).toPromise();
So now you know how to create a multi-user application using the Hyperledger Composer REST Server! But one last thing. If you have tried running the app you may have noticed alot of pictures of penguins. These are all penguins owned by the Hyperledger Composer team and are given to (or thrown at) people who break the build!
https://medium.com/#CazChurchUk/developing-multi-user-application-using-the-hyperledger-composer-rest-server-b3b88e857ccc

SignalR - The connection id is in the incorrect format when using Windows and Anonymous authentication

I use SignalR 1.0.1 as a chat core for ASP.NET MVC3 application. Using IIS 7.5
There are two methods in MVC controller which provides access to chat views:
1. First method is public, allowing anonymous users to chat - no authorization.
2. Access to second method is restricted with [Authorize] attribute, for domain users - chat agents.
There is no explicitly specified authorization in the Hub.
For this scenario I involved both Windows and Anonymous authentication on IIS.
I also implemented custom Role Provider, which operates only in memory - not persisting anything to database.
What happens is that using '[Authorize]' attribute in controller method leads to responsing 500 from Hub, both when call is coming from authorized view, and the anonymous one:
Request (send is Hub method for sending messages):
http://localhost:8101/signalr/send?transport=serverSentEvents&connectionToken=VIXEZzWQSn5SNlA8RUy4iaOPDFdvuPBjMvFBiG2FLfvfxF347XHwtapsEV5ndU4OEI0Xb64W2ZRXTqwBiL2CXg2_JlTaTJ2RnVOj4bjvx6tQaYhAqTaXs9k2853GYqzd0
Response:
The connection id is in the incorrect format.
Server stack trace:
at Microsoft.AspNet.SignalR.PersistentConnection.GetConnectionId(HostContext context, String connectionToken)
at Microsoft.AspNet.SignalR.PersistentConnection.ProcessRequest(HostContext context)
at Microsoft.AspNet.SignalR.Owin.CallHandler.Invoke(IDictionary2 environment)
at Microsoft.AspNet.SignalR.Owin.Handlers.HubDispatcherHandler.Invoke(IDictionary2 environment)
at Microsoft.Owin.Host.SystemWeb.OwinCallContext.Execute()
at Microsoft.Owin.Host.SystemWeb.OwinHttpHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object extraData)<br/><br/>
But notice, that connecting to Hub works fine, returns 200 OK:
http://localhost:8101/signalr/connect?transport=serverSentEvents&connectionToken=dYOwFxa1mkgdpzw-jitRpWq9oxRlrTet8U_dAzWjFQEdGNJfVXeG7Op0NZZwvznxeNdJCuPT75CKzQqI9HRPThV3uEDt-Z2qtIl9E02gF481&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=9
I found little similiar thread here on stackoverflow:
signalr The connection id is in the incorrect format
from which I understand, that when invoking my Send method, the Hub is processing request with Identity different than the one used to connect to Hub, OR Hub's GetConnectionId finds, that user is actually not authorized - but how it checks that assumption, when there is no authorization specified on the Hub itself?
Can someone put some light on this?
Thanks in advance :)
SignalR signs both your connection id and your Identity together in order to create a new connectionToken every time you start a new connection. This connectionToken is then sent to the SignalR client as part of the negotiate response.
Every time you make a request to SignalR, whether it be a connect, reconnect, or send request, SignalR verifies that your connectionToken matches both your client's connection id AND Identity.
The connectionToken is essentially a CSRF token used in order to prevent attackers running third-party websites from surreptitiously making SignalR requests on behalf of shared clients. Obviously this doesn't help if you've enabled SignalR's cross-domain support, but the connectionToken still works the same in this case.
Taylor's answer was correct. You should stop and then start your SignalR connection when your client's Identity changes. This will force a new negotiate request which will give your client a new connection id with a new connectionToken signed with your client's updated Identity.
P.S. The server-sent events connect request isn't failing because it was established before your client's Identity was changed. The connectionToken is only checked at the request is received, but server-sent events keeps the response open indefinitely.
That's all true what you said and it actually takes place in my issue.
But I also found the the root cause:
One of main assumptions during design was to allow both anonymous users to use the chat without need to sign-in and the back-end users (agents) to sign-in to restricted area of chat using their Windows credentials.
So on the IIS manager I enabled both Anonymous authentication (allowing anonymous users to use the chat) and the Windows authentication (allowing agents to access using their Windows credentials).
MVC application is configured to use Windows authentication - the [Authorize] attribute mentioned in question, but only to restrict access for agent's view of chat.
What actually happens with above configuration is:
1. When client (agent) requests restricted View (let's say it's /Chat/Agent) the [Authorize] attribute initializes authentication (Windows)
2. Client-side Javascript requests Negotiate, what generates connectionId and binds it with client's Windows Identity
3. Here is the tricky part: Because Hub not uses any authentication explicitly, calling send method does not result in any authentication request - IIS Anonymous authentication takes precedency before Windows authentication, and send request is sent with anonymous Identity - but in Hub actual connectionId is related to Identity passed in point 2.
This scenario leads to situation you described - connect is called with different Identity than send and Hub returns The connection id is in the incorrect format.

TFS 2010 - Access Denied to Administrator for '/tfs'

I'm trying to set up a TFS2010 (with SP1) server and I keep running into hurdles.
The latest prevents me from doing anything useful as every HTTP request to "https://tfs.myserver.com/tfs" results in a HTTP 401. It doesn't matter if these requests come from the TFS Administration Console or from a web-browser. Every time I'm prompted to authenticate I enter the domain Administrator's fully-qualified username and password and I always get this error message:
Team Foundation Server
TF30063: You are not authorized to access https://tfs.myserver.com/tfs. - The remote erver returned an error: (401) Unauthorized.
Only a few settings in the Administration Console work (such as "Change URLs") but others, like "Group Membership" (either on the Application Tier node or on a Team Project Collection) results in the same prompt-then-fail.
The SSL certificate is valid, and the URLs seem consistent. I can't think what I'm missing out on.
EDIT: There is nothing relevant in the usual Event Logs. The Security log does show my Audit Failures, but I don't understand them because I'm entering the usernames and passwords correctly (the very same I use to access the servers over RDP):
An account failed to log on.
Subject:
Security ID: NULL SID
Account Name: -
Account Domain: -
Logon ID: 0x0
Logon Type: 3
Account For Which Logon Failed:
Security ID: NULL SID
Account Name: Administrator
Account Domain: DOMAIN
Failure Information:
Failure Reason: Unknown user name or bad password.
Status: 0xc000006d
Sub Status: 0xc000006a
What's different about Group Membership & security dialogs is they go through the client APIs and access via IIS. All others such as change server urls go through the server model straight to the DBs. That means IIS cannot authenticate on your domain for some reason ...
From the description, it seems like a domain joined machine. Does IIS have access to the domain controllers? (is it connected to the domain network) The wizards verify you can reach AD but if you disconnect afterwards ... If IIS can't reach AD it will not be able to authenticate. TFS relies on IIS for windows authentication. It appears it can't do that.
Some other things to try:
On the application tier panel of the admin console, try changing the account (domain account) that the server runs as.
Did you choose Kerberos authentication in the advanced wizard? If you do that with a domain user as the service account, there's a pop-up dialog telling you that you need extra AD administration. If you did that, you can change to NTLM from the admin console.
Try to access it via http://machinename:8080/tfs (instead of FQDN) both locally and remotely. Try http://machinename:8080/tfs/web from the web browser as well. make sure you're not having a proxy server issue (routing NTLM through proxy servers can be problematic - if you have bypass local in IE settings then address without dots won't route through the proxy and takes that out of the troubleshooting picture). You can also completely disable proxy in IE just for troubleshooting.
Create another web site manually with a hello world aspx running as the same account with anonymous & basic auth disabled and integrated windows auth enabled. Ensure it works.
After growing frustrated with trying the helpful suggestions people made but not getting anywhere I decided to start-over and try again. I completely uninstalled TFS, SQL Server, and SharePoint services and reinstalled from scratch.
This time it worked fine - no meddling with security was necessary and the system just worked out-of-the-box.
Looking back, I think the problem was that I set-up TFS with the advanced option to use SharePoint, and then I probably fiddled around with settings I wasn't familar with and ended up making a hash of things.
Note to future self: practice in a VM before deploying in production.

Resources