The 26-year-old goalkeeper had been on loan at Parkhead since January, making six appearances as the Hoops sealed the Scottish Premiership title.
Originally signed as cover until the summer, Bain has now secured a long-term contract with the Glasgow club.
"I'm delighted," Bain told Celtic TV. "It's more than I obviously expected when I first came in. I'm over the moon. I don't think it could have gone any better.
"It's funny, there's a lot of little things that went my way to get to Celtic on loan and then to play the game against Rangers, which sent me on my way to this four-year-deal. It's been great and I've loved every minute of it."
Bain had not played since late October when he made his Celtic debut in the 3-2 win at Rangers in March.